9742
Классы и объекты в Object Pascal
Реферат
Информатика, кибернетика и программирование
Классы и объекты Классами в Object Pascal называются специальные типы, которые содержат поля, методы и свойства. Как и любой другой тип, класс служит лишь образцом для создания конкретных экземпляров реализации, которые называются объектами. Сразу ж...
Русский
2013-03-15
82.5 KB
66 чел.
Классами в Object Pascal называются специальные типы, которые содержат поля, методы и свойства. Как и любой другой тип, класс служит лишь образцом для создания конкретных экземпляров реализации, которые называются объектами. Сразу же уточню, что в предшественнике Object Pascal - Turbo Pascal объектами называются типы, имеющие много общего с классами Object Pascal. Однако существенные усовершенствования, внесенные в объектную модель Object Pascal, заставили разработчиков языка ввести для обозначения объектов специальный термин - класс, заимствованный, кстати, из Си++. Для совместимости с ранее разработанными программами системы Turbo Pascal with Objects 7.0 в Object Pascal сохранен тип-объект Object, поддерживающий «старую» объектную модель. Поскольку все возможности этой модели доступны классам, мы не будем рассматривать ее, а «освободившийся» термин объект будем употреблять исключительно для обозначения конкретного экземпляра реализации класса.
Важным отличием классов от других типов является то, что объекты класса всегда распределяются в куче, поэтому объект-переменная фактически представляет собой лишь указатель на динамическую область памяти. Однако, в отличие от других указателей, при ссылке на содержимое объекта запрещается использовать символ «^» за именем объекта:
type
TMyClass = class(TObject)
Field: Integer;
...
end;
var
MyClass: TMyClass;
begin
...
MyClass^.Field := 0; // Ошибка!. Следует писать так:
MyClass.Field := 0;
end;
Классы - это особое «изобретение» программистов для упрощения разработки сложных программ и улучшения их качества. В основе классов лежат три фундаментальных принципа, которые называются инкапсуляция, наследование и полиморфизм.
Класс представляет собой единство трех сущностей - полей, методов и свойств. Объединение этих сущностей в единое целое и называется инкапсуляцией. Инкапсуляция позволяет во многом изолировать класс от остальных частей программы, сделать его «самодостаточным» для решения конкретной задачи. В результате класс всегда несет в себе некоторую функциональность. Например, класс TForm содержит (инкапсулирует в себе) все необходимое для создания Windows-окна, класс ТМеmо представляет собой полнофункциональный текстовый редактор, класс TTimer обеспечивает работу программы с таймером и т.д..
Инкапсуляция представляет собой мощное средство обмена готовыми к работе программными заготовками. Библиотека классов Delphi - это, фактически, набор «кирпичиков», созданных программистами Borland для построения ваших программ.
Любой класс может быть порожден от другого класса. Для этого при его объявлении указывается имя класса-родителя:
TChildClass = class(TParentClass)
Порожденный класс автоматически наследует поля, методы и свойства своего родителя и может их добавлять новыми. Таким образом, принцип наследования обеспечивает поэтапное создание сложных классов и разработку собственных библиотек классов.
Все классы Object Pascal порождены от единственного родителя класса TObject. Этот класс не имеет полей и свойств, но включает в себя методы самого общего назначения, обеспечивающие весь жизненный цикл любых объектов - от их создания до уничтожения. Программист не может создать класс, который не был бы дочерним классом TObject. Следующие два объявления идентичны:
TaClass = class(TObject)
TaClass = class
Принцип наследования приводит к созданию ветвящегося дерева классов, постепенно разрастающегося при перемещении от TObject к его потомкам. Каждый потомок дополняет возможности своего родителя новыми и передает их своим потомкам.
Для примера на рис. 1 показан небольшой фрагмент дерева классов Delphi. Класс TPersistent обогащает возможности своего родителя TObject: он «умеет» сохранять данные в файле и получать их из него, в результате это умеют делать и все его потомки. Класс TComponent, в свою очередь, умеет взаимодействовать со средой разработчика и передает это умение своим потомкам. TControl не только способен работать с файлами и средой разработчика, но он еще умеет создавать и обслуживать видимые на экране изображения, а его потомок TWinControl может создавать Windows-окна и т.д.
Рис. 1. Фрагмент дерева классов Object Pascal
Полиморфизм - это свойство классов решать схожие по смыслу проблемы разными способами. В рамках Object Pascal поведенческие свойства класса определяются набором входящих в него методов. Изменяя алгоритм того или иного метода в потомках класса, программист может придавать этим потомкам отсутствующие у родителя специфические свойства. Для изменения метода необходимо перекрыть его в потомке, т.е. объявить в потомке одноименный метод и реализовать в нем нужные действия. В результате в объекте-родителе и объекте-потомке будут действовать два одноименных метода, имеющие разную алгоритмическую основу и, следовательно, придающие объектам разные свойства. Это и называется полиморфизмом объектов.
В Object Pascal полиморфизм достигается не только описанным выше механизмом наследования и перекрытия методов родителя, но и их виртуализацией (см. ниже), позволяющей родительским методам обращаться к методам своих потомков.
Полями называются инкапсулированные в классе данные. Поля могут быть любого типа, в том числе - классами, например:
type
TMyClass = class
aIntField: Integer;
aStrField: String;
aObjField: TObject;
. . .
end;
Каждый объект получает уникальный набор полей, но общий для всех объектов данного класса набор методов и свойств. Фундаментальный принцип инкапсуляции требует обращаться к полям только с помощью методов и свойств класса. Однако в Object Pascal разрешается обращаться к полям и напрямую. Для этого используются составные имена полей, содержащие имя объекта в качестве префикса:
var
aObject: TMyClass;
begin
aObject.aIntField := 0;
aObject.aStrField := 'Строка символов';
end;
Класс-потомок получает все поля всех своих предков и может дополнять их своими, но он не может переопределять их или удалять. Таким образом, чем ниже в дереве иерархии располагается класс, тем больше данных получают в свое распоряжение его объекты.
Инкапсулированные в классе процедуры и функции называются методами. Они объявляются так же, как и обычные подпрограммы:
type
TMyClass = class
function MyFunc(aPar: Integer): Integer;
procedure MyProc;
end;
Доступ к методам класса, как и к его полям, возможен с помощью составных имен:
var
aObject: TmyClass
begin
. . .
aObject.MyProc;
. . .
end;
Как уже говорилось, методы класса могут перекрываться в потомках. Например:
type
TParentClass = class
procedure DoWork;
end;
TChildClass = class(TParentClass)
procedure DoWork;
end;
Потомки обоих классов могут выполнять сходную по названию процедуру DoWork, но, в общем случае, будут это делать по-разному. Такое замещение методов называется статическим, т.к. реализуется компилятором.
В Object Pascal гораздо чаще используется динамическое замещение методов на этапе прогона программы. Для реализации этого метод, замещаемый в родительском классе, должен объявляться как динамический (с директивой dynamic) или виртуальный (virtual). Встретив такое объявление, компилятор создаст две таблицы - DMT (Dynamic Method Table) и VMT (Virtual Method Table) и поместит в них адреса точек входа соответственно динамических и виртуальных методов. При каждом обращении к замещаемому методу компилятор вставляет код, позволяющий извлечь адрес точки входа в подпрограмму из той или иной таблицы. В к,лассе-потомке замещающий метод объявляется с директивой override. Получив это указание, компилятор создаст код, который на этапе прогона программы поместит в родительскую таблицу точку входа метода класса-потомка, что позволит родителю выполнить нужное действие с помощью нового метода.
Пусть, например, родительский класс с помощью методов 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 у объекта, затем - у его родительского класса и так далее, пока не будет найдена нужная точка входа.
Динамически перекрываемые методы часто могут вообще ничего не делать. Такие методы называются абстрактными, они обязаны перекрываться в потомках. Программист может запретить вызов абстрактного метода, объявив его с директивой abstract. Например:
type
TVisualObject = class(TWinControl)
procedure Draw(IsShow:Boolean); virtual; abstract;
end;
TVisualChildObject = class(TWinControl)
procedure Draw(IsShow: Boolean); override;
end;
var
aVisualObjoect: TVisualObject;
aVisualChild: TVisualChildObject;
begin
aVisualObject.Show;// Ошибка! Обращение к абстрактному методу
aVisualChild.Show;// Нормальное обращение. Метод Draw у класса
// TVisualChildObject перекрыт.
end;
Вызов не перекрытого абстрактного метода вызывает ошибку периода исполнения. Разумеется, в грамотно составленной программе абстрактные методы никогда не вызываются. Классы, содержащие абстрактные методы, называются абстрактными. Такие классы инкапсулируют общие свойства своих неабстрактных потомков, но объекты абстрактных классов никогда не создаются и не используются. Для эксплуатации абстрактных классов в библиотеку классов Delphi включаются классы-потомки, в которых перекрываются абстрактные методы родителя.
В состав любого класса входят два специальных метода - конструктор и деструктор. У класса TObject эти методы называются Create и Destroy, так же они называются в подавляющем большинстве его потомков. Конструктор распределяет объект в динамической памяти и помещает адрес этой памяти в переменную Self, которая автоматически объявляется в классе. Деструктор удаляет объект из кучи. Обращение к конструктору должно предварять любое обращение к полям и некоторым методам объекта. По своей форме конструкторы и деструкторы являются процедурами, но объявляются с помощью зарезервированных слов Constructor и Destructor.
type
TMyClass = class
IntField: Integer;
Constructor Create(Value: Integer);
Destructor Destroy;
end;
Любые поля объекта, а также методы класса, оперирующие с его полями, могут вызываться только после создания объекта с помощью вызова конструктора, т.к. конструкторы распределяют объект в динамической памяти и делают действительным содержащийся в объекте указатель.
var
MyObject: TMyClass;
begin
MyObject.IntField := 0; // Ошибка! Объект не создан конструктором!
MyObject := TMyClass.Create; // Надо так: создаем объект
MyObject.IntField := 0; // и обращаемся к его полю.
MyObect.Free; // Уничтожаем ненужный объект
end;
В базовом классе TObject определен метод Free, который сначала проверяет действительность адреса объекта и лишь затем вызывает деструктор Destroy. Обращение к деструктору объекта будет ошибочным, если объект не создан конструктором, поэтому для уничтожения ненужного объекта следует вызывать метод Free, как это сделано в предыдущем примере.
Большинство конструкторов реализуют некоторые действия, необходимые для правильной работы объекта. Поэтому в конструкторе класса-потомка следует сначала вызвать конструктор своего родителя, а уже затем осуществлять дополнительные действия. Вызов любого перекрытого метода родительского класса достигается с помощью зарезервированного слова Inherited (унаследованный) :
Constructor TMyClass.Create(Value: Integer);
// Возможная реализация конструктора
begin
Inherited Create; // Вызываем унаследованный конструктор
IntField := Value;// Реализуем дополнительные действия
end;
Некоторые методы могут вызываться без создания и инициации объекта. Такие методы называются методами класса, они объявляются с помощью зарезервированного слова class:
type
TMyClass = class(TObject)
class function GetClassName: String;
end;
var S: String;
begin
S := TMyClass.GetClassName;
end;
Методы класса не должны обращаться к полям, т.к. в общем случае вызываются без создания объекта, а следовательно, в момент обращения к полям они просто не существуют. Обычно они возвращают служебную информацию о классе - имя класса, имя его родительского класса, адрес метода и т.п..
Свойства - это специальный механизм классов, регулирующий доступ к полям. Свойства объявляются с помощью зарезервированных слов 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;
В контексте программы свойство ведет себя как обычное поле. Например, мы могли бы написать такие операторы:
var
aClass: TaClass;
Value: Integer;
begin
aClass := TaClass.Create; {Обязательное обращение к конструктору
перед обращением к полю или свойству!}
aClass.IntegerValue := 0;
Value := aClass.IntegerValue;
aClass.Destroy; // Удаление ненужного объекта
end;
Более того, возможен и такой оператор присваивания:
aClass.IntField := NewValue;
Разница между этим оператором и оператором
aClass.IntegerValue := NewValue;
заключается в том, что при обращении к свойству автоматически подключается метод SetField, в котором могут реализовываться специфичные действия.
Пример: рассмотрим следующий оператор
IbOutput.Caption := 'Строка';
Свойство Caption компонента Label вызывает метод SetText, который не только запоминает строку символов во внутренней переменной, но и осуществляет прорисовку метки с новым текстом.
Если нет необходимости в специальных действиях при чтении или записи свойства, вместо имени соответствующего метода можно указывать имя поля:
type
TaClass = class
IntField: Integer;
procedure SetField(Value: Integer);
Property IntegerValue: Integer read IntFiled write SetField;
end;
Если необходимо, чтобы поле было доступно только для чтения или только для записи, следует опустить соответственно часть write или read. Вообще говоря, свойство может и не связываться с полем. Фактически оно описывает один или два метода, которые осуществляют некоторые действия над данными того же типа, что и свойство.
Любой вновь создаваемый класс содержит четыре секции, определяемые зарезервированными словами published (декларированные), private (личные), protected (защищенные) и public (доступные). Внутри каждой секции вначале определяются поля, а затем - методы и свойства.
Секции определяют области видимости элементов описания класса. Секция public не накладывает ограничений на область видимости перечисляемых в ней полей, методов и свойств - их можно вызывать в любом другом модуле программы. Секция published так же не ограничивает область видимости, однако в ней перечисляются свойства, которые должны быть доступны не только на этапе исполнения, но и на этапе конструирования программы (т.е. в окне Инспектора Объектов). Секция published используется только при разработке компонентов. Замечу, что по умолчанию (без объявления) секция считается объявленной как published. Такая умалчиваемая секция располагается в самом начале объявления класса любой формы и продолжается до первой объявленной секции. В нее среда Delphi помещает описания вставленных в форму компонентов. Программисту не следует помещать в нее собственные элементы описания класса или удалять из нее элементы, вставленные средой. Секция private сужает область видимости до минимума: личные элементы описания доступны только внутри методов данного класса и подпрограммах, находящихся в том же модуле, где описан класс. Элемент, объявленный в секции private, становится недоступным даже ближайшим потомкам класса, если они размещаются в других модулях. Наконец, секция protected доступна только методам самого класса, а также любым его потомкам, независимо от того, находятся ли они в том же модуле, или нет. В Object Pascal разрешается сколько угодно раз объявлять любую секцию, причем порядок следования секций не имеет значения. Любая секция может быть пустой.
Следующий фрагмент кода поясняет области видимости.
Unit Unit1;
Interface
Uses Controls, Forms;
type
TForml = class(TForm)
Buttonl: TButton; // Эта секция обслуживается Delphi
// Ее элементы доступны всем
private // Эта секция доступна в модуле Unit1
FIntField: Integer;
procedure SetValue(Value: Integer);
function GetValue: Integer;
published // Эта секция доступна в любом модуле
Property IntField: read GetValue write SetValue;
protected // Эта секция доступна классам-потомкам
procedure Proc1;
public // Эта секция доступна в любом модуле
procedure Proc2;
end;
var
Form1: TForm1;
Implementation
procedure TForm1.Proc1;
Buttonl.Color := clBtnFace; // Так можно
FIntField := 0; // Так можно
IntField := 0; // Так можно
Proc1; // Так можно
Рrос2; // Так можно
end;
Initialization
Form1.Button1.Color := clBtnFace; // Так можно
Form1.FIntField := 0; // Так можно
Form1.IntField := 0; // Так можно
Form1.Proc1; // Так нельзя!
Form1.Proc2; // Так можно
end.
Unit Unit2;
Interface
Uses Controls, Unitl;
type
TForm2 = class(TForm1)
Button2: TButton;
procedure Button2Click(Sender: TObject);
end;
var
Form2: TForm2;
Implementation
procedure TForm2.Button2Click(Sender: ТObject);
begin
Button1.Color := clBtnFace; // Так можно
FIntField := 0; // Так нельзя!
IntField := 0; // Так можно
Proc1; // Так можно
Ргос2; // Так можно
end;
Initialization
Form1.Button1.Color := clBtnFace; // Так можно
Form1.FIntField := 0; // Так нельзя!
Form1.IntField := 0; // Так можно
Form1.Proc1; // Так нельзя!
Form1.Proc2; // Так можно
end.
При объявлении класса-потомка разрешается перемещать элементы класса из одной области видимости в другую. Для предыдущего примера допустимо такое объявление:
type
TForm2 = class(TForm1)
Public
procedure Proc1;
end;
После этого в модуле Unit2 возможно такое обращение:
Form2.Proc1;
После перемещения в секцию private элемент объявления становится невидим потомкам (если потомок, как это обычно бывает, объявляется в другом модуле) и, следовательно, его уже нельзя переместить в другую секцию.
Класс может объявляться только в интерфейсной части модуля или в самом начале области реализации. Нельзя определять классы в разделе описаний подпрограмм.
А также другие работы, которые могут Вас заинтересовать | |||
76682. | Стратегічний менеджмент | 66 KB | |
Зона стратегічних ресурсів становить сегмент ринку, на якому діють організації-постачальники певних ресурсів, що можуть суттєво впливати на діяльність організацій – виробників кінцевого продукту за рахунок їх дефіциту, значної конкуренції або обмеженого доступу з інших причин. | |||
76683. | Переломи стегна клінічні ознаки, особливості надання першої медичної допомоги та лікування | 112.5 KB | |
Перелом стегна актуальна проблема для людей, особливо у літніх людей. Перелом стегна в похилому віці може нести небезпечні для життя наслідки, тому даній травмі приділено багато уваги. Можливий перелом стегна зі зміщенням, чрезвертельный, відкритий... | |||
76684. | Boing -747 | 19.14 KB | |
The four-engine 747 uses a double deck configuration for part of its length. It is available in passenger, freighter and other versions. Boeing designed the 747’s hump-like upper deck to serve as a first class lounge or extra seating, and to allow the aircraft to be easily converted... | |||
76685. | РЕФОРМЫ ПЕТРА I И ИХ ЗНАЧЕНИЕ | 108 KB | |
Многие из этих преобразований уходят корнями в XVII век социально-экономические преобразования того времени послужили предпосылками реформ Петра задачей и содержанием которых было формирование дворянско-чиновничьего аппарата абсолютизма. | |||
76686. | ИСКОВАЯ ДАВНОСТЬ | 257.87 KB | |
В юриспруденции учение об исковой давности является одним из фундаментальных, и привлекает к своему исследованию многих ученых цивилистов. Не смотря на то, что дефиниция исковой давности относится к числу теоретических разногласий, институт исковой давности не умаляет своего научного и практического значения. | |||
76687. | Увольнение за утрату доверия к работнику | 21.19 KB | |
Для этого существует статья 81 Расторжение трудового договора по инициативе работодателя в частности пункт 7 данной статьи Увольнение сотрудника в связи с утратой к нему доверия. Так какие же лица подлежат увольнению по данной статье Можем ли мы уволить сотрудника по субъективному мнению о его нечестности... | |||
76690. | Синдром «менеджера» | 815.8 KB | |
Под синдромом менеджера (он же синдром хронической усталости или синдром выгорания) принято считать наличие следующих симптомов: быстрая утомляемость и изматывающая организм усталость, которая не проходит даже после отпуска, апатия, депрессия, беспричинные приступы гнева и др. | |||