9742

Классы и объекты в Object Pascal

Реферат

Информатика, кибернетика и программирование

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

Русский

2013-03-15

82.5 KB

44 чел.

Классы и объекты

Классами в 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 элемент объявления становится невидим потомкам (если потомок, как это обычно бывает, объявляется в другом модуле) и, следовательно, его уже нельзя переместить в другую секцию.

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


 

А также другие работы, которые могут Вас заинтересовать

35515. Лечебное дело. Сборник задач 834.5 KB
  2] Критерии оценки при решении задач по оказанию неотложной помощи [0. Предлагаемый сборник содержит проблемноситуационные задачи задачи по оказанию доврачебной помощи при неотложных состояниях с эталонами ответов. Решение задач предполагает выявить у выпускников способность клинически мыслить распознавать основную клиническую патологию и ее осложнения определять правильную тактику ведения больного и оказание неотложной помощи осуществлять профилактическую и реабилитационную деятельность владеть техникой важнейших лечебнодиагностических...
35516. ТЕРАПИЯ. Сборник клинических задач 775.5 KB
  Эталоны ответов Рекомендуемая литература Инструктивно-методические документы Требования государственного образовательного стандарта к уровню подготовки специалистов в области терапии для специальности 0401 Лечебное дело Фельдшер должен: знать систему организации терапевтической службы; знать причины механизмы развития клинические проявления методы диагностики осложнения принципы лечения и профилактики заболеваний внутренних органов; уметь поставить диагноз в соответствии с современной классификацией; уметь определить тактику...
35517. Гилерболоидные зубчатые передачи 414.5 KB
  Для обеспечения точечного касания линий зубьев можно применить более простые по форме поверхности, чем гиперболоиды вращения, что упрощает изготовление зубчатых колес.
35518. НЕРВНЫЕ БОЛЕЗНИ ПСИХИЧЕСКИЕ БОЛЕЗНИ КОЖНЫЕ И ВЕНЕРИЧЕСКИЕ БОЛЕЗНИ БОЛЕЗНИ УХА, ГОРЛА, НОСА 285 KB
  Глазные болезни Нервные болезни Психические болезни Нуриева Л. Болезни уха горла носа Насыбуллина С. Кожные и венерические болезни Самойлова Л.
35519. ПЕДИАТРИЯ С ДЕТСКИМИ ИНФЕКЦИЯМИ 407.5 KB
  Обучение студентов в медицинском колледже(училище) завершается проведением итоговой аттестации, которая включает в себя вопросы педиатрии с детскими инфекциями. Данное пособие поможет Вам подготовиться к предстоящей аттестации. При подготовке к аттестации следует. Проверить свои знания, ответив на тестовые задания по всем разделам и сверить свои ответы с эталонами. Для оценки знаний пользуйтесь критериями
35520. Лечебное дело. Сборник тестовых заданий 98.5 KB
  Концентрация раствора хлорамина для обработки поверхности загрязненной кровью а 3 б 1 в 05 г 025 2. При попадании хлорсодержащего раствора в глаза медсестры необходимо а промыть раствором гидрокарбоната натрия б закапать раствором альбуцида в немедленно обратиться к врачу г промыть глаза проточной водой 6. Пациент разбил ртутный термометр действие медсестры а собрать в герметичную емкость и сообщить в СЭС б собрать влажным тампоном и выбросить в мусорный контейнер в собрать грушевидным баллоном и вылить в раковину г собрать...
35521. ТЕРАПИЯ. Сборник тестовых заданий 285.5 KB
  При подготовке к аттестации следует: 1. При неудовлетворительной оценке следует вновь проработать учебный материал 3. Повторить решение тестовых заданий Желаем успеха Требования государственного образовательного стандарта к уровню подготовки специалистов в области терапии для специальности 0401 Лечебное дело Фельдшер должен: знать систему организации терапевтической службы; знать причины механизмы развития клинические проявления методы диагностики осложнения принципы лечения и профилактики заболеваний внутренних органов; уметь...
35522. МЕДИЦИНА КАТАСТРОФ. АКУШЕРСТВО. ГИНЕКОЛОГИЯ. КЛИНИЧЕСКАЯ ФАРМАКОЛОГИЯ. ИНФЕКЦИОННЫЕ БОЛЕЗНИ С ЭПИДЕМИОЛОГИЕЙ 167.5 KB
  Для профилактики раневой инфекции на первом этапе медицинской эвакуации применяют: а первичную хирургичесую обработку ран наложение асептической повязки б антибиотикотерапию обезболивание инфузионную терапию в транспортную иммобилизацию обезболивание г наложение асептической повязки антибиотикотерапию 19. Для профилактики раневой инфекции на первом этапе медицинской эвакуации применяют: а первичную хирургичесую обработку ран наложение асептической повязки б антибиотикотерапию обезболивание инфузионную терапию в транспортную...
35523. КОМПАС - ГРАФИК LT 5.10. Краткое руководство пользователя 159.5 KB
  Открыть: страницу меню Файл команды Создать и Лист. Открыть: страницу меню Настройка команды Параметры текущего листа Параметры листа. Открыть команду Оформление выбрать тип основной надписи: Чертеж констр. открыть нужную папку по указанию.