КАТЕГОРИИ: Архитектура-(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; Просмотров: 462; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |