Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Свойства




Var

МЕТОДЫ

ПОЛЯ

Класс представляет собой единство трех сущностей - полей, методов и свойств. Объединение этих сущностей в единое целое достигается за счет применения инкапсуляции.

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

type

TMyClass = class

aIntField: Integer; aStrField: String; aObjField: TObject;

end;

Каждый объект получает уникальный набор полей, но общий для всех объектов данного класса набор методов и свойств. Фунда­ментальный принцип инкапсуляции требует обращаться к полям только с помощью методов и свойств класса. Однако в Object Pascal разрешается обращаться к полям и напрямую. Для этого ис­пользуются составные имена полей, содержащие имя объекта в ка­честве префикса.

type

TMyClass = class

aIntField: Integer; aStrField: String;

end; var

aObject: TMyClass; begin

aObject.aIntField: = 0;

aObject.aStrField: = 'Строка символов';

end;

Класс-потомок получает все поля своих предков и может до­полнять их своими, но он не может переопределять их или удалять. Таким образом, чем ниже в дереве иерархии располагается класс, тем больше данных получают в свое распоряжение его объекты.

Методы представляют собой процедуры и функции, принадлежащие заданному объекту. Поэтому методы определяют поведение объекта. Для класса можно самостоятельно создать про­извольное количество любых методов, необходимых для решения конкретных задач. Создание метода осуществляется в два этапа. Сначала следует описать метод в объявлении типа, а затем создать текст его реализации. Вот пример описания и определения метода:

type

TMyClass = class Work: Boolean; procedure DoWork; end;

procedure TMyClass.DoWork; begin

Work:= True; end;

При определении тела метода необходимо использовать его полное имя с указанием класса. Вторая важная деталь - к любому полю объекта его метод может обратиться непосредственно. Дос­туп к методам класса, как и к его полям, возможен с помощью со­ставных имен.

var

aObject: TMyClass; begin

aObject.DoWork;

end;

Статические методы. Как уже говорилось, методы клас­са могут перекрываться в потомках. Например:

type

TParentClass = class

procedure DoWork; end;

TChildClass = class(TparentClass)

procedure DoWork; end;

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

Статический метод DoWork работает подобно обычной проце­дуре или функции. Этот тип методов принимается по умолчанию. Адрес такого метода известен уже на стадии компиляции, и компи­лятор в тексте программы оформляет все вызовы данного метода как статические. Такие методы работают быстрее других, однако не могут быть перегружены для поддержки полиморфизма объектов.

Динамические и виртуальные методы. В Object Pascal гораздо чаще используется динамическое замещение мето­дов на этапе прогона программы. Для реализации этого, метод, за­мещаемый в родительском классе, должен объявляться как дина­мический (с директивой dynamic) или виртуальный (virtual). тив такое объявление, компилятор создаст две таблицы - DMT (Dynamic Method Table) и VMT (Virtual Method Table) и поместит в них адреса точек входа соответственно динамических и вирту­альных методов.

При каждом обращении к замещаемому методу компилятор вставляет код, позволяющий извлечь адрес точки входа в подпро­грамму из той или иной таблицы. В классе потомке замещающий метод объявляется с директивой override, которая вызывает за­мещение строки описания исходного метода в VMT строкой описа­ния нового метода. Получив такое указание, компилятор создаст код, который на этапе прогона программы поместит в родитель­скую таблицу точку входа метода класса-потомка, что позволит родителю выполнить нужное действие с помощью нового метода.

Например, родительский класс с помощью методов Show и Hide соответственно показывает что-то на экране или прячет изображе­ние. Для создания изображения он использует метод Draw с логи­ческим параметром:

type

TVisualObject = class(TWinControl)

procedure Hide;

procedure Show;

procedure Draw(IsShow: Boolean); virtual; end; TVisualChildObject = class(TVisualObject)

procedure Draw(IsShow: Boolean); override; end;

Реализация методов Show и Hide выглядит следующим образом:

procedure TVisualObject.Show; begin

Draw(True); end;

procedure TVisualObject.Hide begin

Draw(False); end;

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

Разница между динамическими и виртуальными методами со­стоит в том, что таблица динамических методов DMT содержит адреса только тех методов, которые объявлены как dynamic в дан­ном классе, в то время как таблица VMT содержит адреса вирту­альных методов не только данного класса, но и всех его родителей. Большая по размеру таблица VMT обеспечивает более быстрый по­иск, в то время как при обращении к динамическому методу про­грамма сначала просматривает таблицу DMT у объекта, затем - у его родительского класса и так далее, пока не будет найдена нужная точка входа.

Конструкторы и деструкторы. В Object Pascal объек­ты создаются с помощью вызова одного из конструкторов этого объекта. Конструктор отвечает за создание объекта, а также за вы­деление памяти и необходимую инициализацию полей. Он распре­деляет объект в динамической памяти и помещает адрес этой памя­ти в переменную Self, которая автоматически объявляется в классе. Конструктор не только создает объект, но и приводит его в состоя­ние, необходимое для его дальнейшего использования.

У класса TObject конструктор называется Create(), так же он на­зываются в подавляющем большинстве его потомков. Каждый объ­ект содержит, по крайней мере, один такой конструктор, который может иметь различное число параметров разного типа — в зависи­мости от типа объекта.

Функцией деструктора является удаление объекта из памяти. По своей форме конструкторы и деструкторы являются процеду­рами, но объявляются с помощью зарезервированных слов Constructor и Destructor:

type

TMyClass = class

IntField: Integer;

Constructor Create(Value: Integer); Destructor Destroy; end;

В отличие от C++, в Object Pascal конструкторы автоматически не вызываются. Каждый объект создается с помощью вызова его конструктора. Обращение к конструктору должно предварять лю­бое обращение к полям и некоторым методам объекта. Синтаксис вызова конструктора следующий:

MyObject: TMyClass; begin

MyObject.IntField:= 0; {Ошибка! Объект не создан

конструктором}

MyObject:= TMyClass.Create; //Нужно создать объект MyObject.IntField:= 0; //и обратиться к его полю

MyObject.Free; //Уничтожаем ненужный объект

end;

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

При создании объекта с помощью конструктора компилятор га­рантирует, что все поля объекта будут инициализированы. Все чи­словые поля будут обнулены, указатели примут значение Nill, а строки будут пусты.

С помощью метода Free() освобождается выделенная для объ­екта память после его использования. Этот метод проверяет, не ра­вен ли объект значению Nill, и затем вызывает деструктор объек­та - метод Destroy(), который освобождает всю выделенную память и выполняет другие действия по освобождению захваченных кон­структором объекта ресурсов. В отличие от вызова конструктора, вызов метода Free() выполняется с помощью ссылки на экземпляр, а не на класс.

Большинство конструкторов реализует некоторые действия, не­обходимые для правильной работы объекта. Поэтому в конструк­торе класса потомка следует сначала вызвать конструктор своего родителя, а затем уже осуществлять дополнительные действия. Вы­зов любого метода родительского класса достигается с помощью ключевого слова Inherited (унаследованный). Например:

Constructor TmyClass.Create(Value: Integer);

//Возможная реализация конструктора

begin

Inherited Create; {Вызываем унаследованный

конструктор}

IntField:= Value; { Реализуем дополнительные действия} end;

 

В большинстве примеров, поставляемых вместе с Delphi, нет вы­зовов конструкторов и деструкторов. Это объясняется тем, что лю­бой компонент, попавший при визуальном проектировании в при­ложение из палитры компонентов, включается в определенную ие­рархию, которая замыкается на форме TForm, а для всех ее составных частей конструкторы и деструкторы вызываются автома­тически. Создает и уничтожает формы глобальный объект с именем Application. Для объектов, создаваемых динамически (во время вы­полнения приложения), обязательно нужен вызов конструктора.

Свойства объекта представляют собой специальный механизм классов, регулирующий доступ к полям объекта. По от­ношению к компонентам свойства являются теми элементами, све­дения о которых отображаются в окне Object Inspector.

Свойства объявляются с помощью зарезервированных слов property, read и write. Слова read и write считаются зарезер­вированными только в контексте объявления свойства. Обычно свойство связано с некоторым полем и указывает те методы класса, которые должны использоваться при записи в это поле или при чтении из него. Например:

type

TaClass = class

IntField: Integer;

function GetField: Integer;

procedure SetField(Value: Integer);

property IntegerValue: Integer read GetField

write SetField; end;

В контексте программы свойство ведет себя как обычное поле. Поэтому возможен следующий оператор присваивания:

aClass.IntField:= NewValue;

Разница между этим оператором и оператором aCIass.IntegerValue:= NewValue;

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

Когда нет необходимости в специальных действиях при чтении или записи свойства, вместо имени соответствующего метода мож­но указывать имя поля. Если нужно, чтобы поле было доступно только для чтения или только для записи, следует опустить соот­ветственно часть write или read.

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

4.7. ОПРЕДЕЛЕНИЕ ОБЛАСТИ ВИДИМОСТИ КЛАССА

Object Pascal предоставляет дополнительный контроль над доступностью членов классов (полей и методов) с помощью директив private, protected, public, published. Синтаксис использования этих директив следующий:

type

TMyClass = class private

AprivateVariable: Integer; AnotherPrivateVariable: Boolean; protected

procedure AProtectedProcedure; function ProtectMe: Byte; public

constructor APublicContructor; destructor APublicKiller; published property AProperty

read AprivateVariable write APrivateVariable; end;

За каждой из директив может следовать любое необходимое количество объявлений полей или методов. Эти директивы имеют следующий смысл.

private - эта часть объекта доступна только для кода, нахо­дящегося в одном модуле с другим кодом данного объекта. Директива private скрывает особенности реализации объекта от поль­зователей и защищает члены этого объекта от непосредственного доступа и изменения извне.

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

public - описанные подобным образом члены объекта доступ­ны в любом месте данной программы. В этой секции всегда описы­ваются конструкторы и деструкторы.

published - для этой части объекта при компиляции будет сгенерирована информация о типе времени исполнения. Это даст возможность другим частям приложения получать информацию о части объекта, описанной в этой секции. В частности, подобная информация используется утилитой Object Inspector при построе­нии списков свойств объектов.

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




Поделиться с друзьями:


Дата добавления: 2014-12-16; Просмотров: 439; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.046 сек.