type

Complex = record

...

class functionoperator implicit(d: real): Complex;

begin

Result.re := d;

Result.im := 0;

end;

class functionoperator explicit(c: Complex): string;

begin

Result := Format('({0},{1})',c.re,c.im);

end;

class procedureoperator+=(var c: Complex; value: Complex);

begin

c.re += value.re;

c.im += value.im;

end;

class functionoperator+(c,c1: Complex): Complex;

begin

Result.re := c.re + c1.re;

Result.im := c.im + c1.im;

end;

end;

Можно перегружать операции с помощью методов расширения - в этом случае при описании подпрограммы не писать слово class. Например, так в системном модуле реализовано добавление числа к строке:

function string.operator+(str: string; n: integer): string;

begin

result := str + n.ToString;

end;

<p>Классовые поля, методы и конструкторы</p>

В классе можно объявить так называемые классовые (статические) поля и методы. Они не принадлежат конкретному экземпляру класса, а связаны с классом. Для их вызова используется точечная нотация, причем, перед точкой используется не имя объекта, а имя класса. Чтобы поле или метод сделать классовым (статическим), перед его именем следует указать ключевое слово class.

Например, определим для класса Person количество созданных объектов этого класса как статическое поле и организуем доступ к этому полю на чтение с помощью статической функции. После каждого вызова конструктора значение статического поля будет увеличиваться на 1:

type

Person = class

private

name: string;

age: integer;

class cnt: integer := 0;

public

constructor (n: string; a: integer);

begin

cnt += 1;

name := n;

age := a;

end;

class function Count: integer;

begin

Result := cnt;

end;

end;

begin

var p: Person := new Person('Иванов',20);

var p1: Person := new Person('Петров',18);

writeln(Person.Count); // обращение к классовому методу Count

end.

В отличие от классовых полей и методов, обычные поля и методы называются экземплярными. Из обычных методов можно обращаться к экземплярным и классовым полям, но из классовых методов можно обращаться только к классовым полям.

Аналогично можно определить также классовый (статический) конструктор, предназначенный для автоматической инициализации классовых полей. Классовый конструктор описывается с ключевым словом class и гарантированно вызывается перед вызовом любого статического метода и созданием первого объекта этого класса.

Например, определим в классе Person классовое поле - массив объектов типа Person - и инициализируем его в классовом конструкторе. Потом указанный массив можно использовать в реализации классовой функции RandomPerson, возвращающей случайный объект типа Person:

type

Person = class

private

class arr: array of Person;

name: string;

age: integer;

public

class constructor;

begin

SetLength(arr,3);

arr[0] := new Person('Иванов',20);

arr[1] := new Person('Петрова',19);

arr[2] := new Person('Попов',35);

end;

//...

classfunction RandomPerson: Person;

begin

Result := arr[Random(3)];

end;

end;

const cnt = 10;

begin

var a := new Person[cnt];

for var i:=0 to a.Length-1 do

a[i] := Person.RandomPerson;

end.

<p>Методы расширения</p>

Любой существующий класс, хранящийся во внешней dll, и все классы стандартной библитеки .NET можно расширить новыми методами. Такие методы расширения отличаются от обычных подпрограмм тем. что перед именем подпрограммы ставится имя расширяемого класса с точкой. Например:

procedure integer.Print;

begin

write(Self)

end;

begin

var i := 1;

i.Print;

end.

Можно расширить интерфейс, тогда все классы, реализующие этот интерфейс, получат этот метод. Например, в системном модуле PABCSystem так расширен стандартный интерфейс IEnumerable методом Print:

Перейти на страницу:

Похожие книги