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;
Классовые поля, методы и конструкторы
В классе можно объявить так называемые
Например, определим для класса 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.
Методы расширения
Любой существующий класс, хранящийся во внешней dll, и все классы стандартной библитеки .NET можно расширить новыми методами. Такие методы расширения отличаются от обычных подпрограмм тем. что перед именем подпрограммы ставится имя расширяемого класса с точкой. Например:
procedure integer.Print;
begin
write(Self)
end;
begin
var i := 1;
i.Print;
end.
Можно расширить интерфейс, тогда все классы, реализующие этот интерфейс, получат этот метод. Например, в системном модуле PABCSystem так расширен стандартный интерфейс IEnumerable