Выбрать главу

end;

...

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

writeln(p); // Имя: Иванов Возраст: 20

Присваивание и передача в качестве параметров подпрограмм

Переменная типа класс является ссылкой и хранит ссылку на объект, создаваемый вызовом конструктора.

Как ссылка переменная типа класс может хранить значение nil:

p := nil;

...

if p = nil then ...

При присваивании переменных типа класс копируется только ссылка. После присваивания обе переменные типа класс будут ссылаться на один объект и совместно модифицировать его:

var p1,p2: Person;

...

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

p2 := p1;

p1.IncAge;

p2.Print; // Имя: Петров Возраст: 21

Сравнение на равенство

При сравнении переменных типа класс на равенство сравниваются ссылки, а не значения.

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

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

writeln(p1=p2); // False

p2 := p1;

writeln(p1=p2); // True

Это поведение можно изменить, перегрузив операцию = для класса.

Видимость членов класса и модификаторы доступа

Каждое поле, метод или свойство класса имеет модификатор (атрибут) доступа, задающий правила его видимости. В PascalABC.NET существуют четыре вида модификаторов доступа: public (открытый), private (закрытый), protected (защищенный) и internal (внутренний). К члену класса, имеющему атрибут public, можно обратиться из любого места программы, члены класса с атрибутом private доступны только внутри методов этого класса, члены класса с атрибутом protected доступны внутри методов этого класса и всех его подклассов, члены класса с атрибутом internal доступны внутри сборки (термин .NET, сборка в нашем понимании - это множество файлов, необходимых для генерации .exe или .dll-файла). Кроме того, private и protected члены видны отовсюду в пределах модуля, в котором определен класс.

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

Например, пусть данный код располагается в одном модуле:

type

A = class

private

x: integer;

protected

a: integer;

public

constructor Create(xx: integer)

begin

x := xx; // верно, т.к. внутри метода класса можно обращаться к его закрытому полю x

a := 0; // верно

end;

;

Следующий же код пусть располагается в другом модуле: type

B = class(A)

public

procedure print;

begin

writeln(a); // верно, т.к. a - защищенное поле

writeln(x); // неверно, т.к. х - закрытое поле

end;

end;

...

var b1: B := new B(5);

...

writeln(b1.x); // неверно, т.к. х - закрытое поле

writeln(b1.a); // неверно, т.к. a - защищенное поле

b1.print; // верно, т.к. print - открытый метод

Комментарии по тексту программы описывают верное и неверное в смысле доступа обращение к полям и методам.

Методы

Методы представляют собой процедуры и функции, объявленные внутри класса или записи. Особыми разновидностями методов являются конструкторы, деструкторы и перегруженные операции.

Определение методов можно давать как внутри класса (стиль Java, C#, C++), так и вне класса (стиль Delphi, C++). При определении метода вне интерфейса класса его имя предваряется именем класса с последующей точкой. Например:

type

Rectangle = class

x1,y1,x2,y2: integer;

constructor Create(xx1,yy1,xx2,yy2: integer);

begin

x1 := xx1; x2 := xx2;

y1 := yy1; y2 := yy2;

end;

function Square: integer;

end;

function Rectangle.Square: integer;

begin

Result := abs(x2-x1) * abs(y2-y1);

end;

Обычно когда класс определяется в интерфейсной части модуля, то в интерфейсе класса производят лишь объявление методов, реализацию же методов класса дают в секции реализации модуля.

Методы делятся на классовые и экземплярные. Классовые методы в .NET называются статическими. Объявление классового метода начинается с ключевого слова class. Экземплярные методы можно вызывать только через переменную-объект класса. Классовые же методы не связаны с конкретным экземпляром класса; их следует вызывать в виде:

имя класса.имя метода(параметры)

Внутри классового метода не может быть обращения к полям класса, а может быть только обращение к другим классовым методам. Напротив, экземплярный метод может вызывать классовый.

Например:

type

Rectangle = class

...

class procedure Move(var r: Rectangle; dx,dy: integer);

begin

r.x1 += dx; r.x2 += dx;

r.y1 += dy; r.y2 += dy;

end;

end;

...

var r := new Rectangle(10,10,100,100);

Rectangle.Move(r,5,5);

По существу, классовые методы являются разновидностью глобальных подпрограмм, но находятся внутри класса, что подчеркивает, что они осуществляют действия, связанные именно с этим классом. Класс в этом случае выступает только в роли пространства имен.

Нередко создаются классы, целиком состоящие из классовых методов. Таков, например, класс System.Math, содержащий определения математических подпрограмм.

Инициализаторы полей

При создании объекта его поля инициализируются автоматически нулевыми значениями если они не инициализированы явно. Их инициализация может проводиться как в конструкторе, так и непосредственно при описании. Инициализация поля при описании приводит к тому, что код инициализации вставляется в начало ВСЕХ конструкторов.

Например:

type

A = class

private

x: integer := 1;

y: integer;

l := new List<integer>;

public

constructor Create(xx,yy: integer);

begin

x := xx;

y := yy;

end;

constructor Create;

begin

end;

end;

В данном примере код x:=1; l := new List<integer> вставляется в начало каждого конструктора.