Помощничек
Главная | Обратная связь


Археология
Архитектура
Астрономия
Аудит
Биология
Ботаника
Бухгалтерский учёт
Войное дело
Генетика
География
Геология
Дизайн
Искусство
История
Кино
Кулинария
Культура
Литература
Математика
Медицина
Металлургия
Мифология
Музыка
Психология
Религия
Спорт
Строительство
Техника
Транспорт
Туризм
Усадьба
Физика
Фотография
Химия
Экология
Электричество
Электроника
Энергетика

Объектно-ориентированное программирование



Объектно-ориентированное программирование (ООП) — это технология создания сложного программного обеспечения, которое основано на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию с наследованием свойств.

Основное достоинство ООП — это сокращение количества межмодульных вызовов и уменьшение объемов информации передаваемой между модулями. Это достигается за счет более полной локализации данных и интегрирования их с подпрограммами обработки.

Основные недостатки в ООП — это некоторое снижение быстродействия из-за более сложной организации программной системы, а также, как правило, заметное увеличение объёма бинарного кода (особенно при использовании стандартных библиотек классов в небольших программах) из-за того, что большинство современных компиляторов и компоновщиков не способны выявить и удалить весь код, приходящийся на неиспользуемые классы, виртуальные методы и другие элементы ООП.

В Object Pascal классы задаются с помощью типа object, аналогичного record, который кроме полей данных может содержать заголовки процедур и функций (они называются методами). Имена описываемых методов следуют за именем класса через точку.

Конструктор и деструктор задаются как обычные процедуры, но вместо идентификатора procedure задаются ключевые слова constructor и destructor. Соответственно, в отличие от С++-подобных языков они имеют имя, отличное от имени класса, деструкторов может быть несколько и они могут иметь параметры (на практике эта возможность используется редко, обычно класс имеет единственный деструктор Destroy, переопределяющий виртуальный деструктор класса-родителя).

Поддерживаются единичное наследование, полиморфизм классов, механизм виртуальных методов (слово virtual после заголовка метода класса). Существуют и динамические методы (в TP описываются путём добавления целого числа после слова virtual и используются преимущественно для обработки сообщений; в Delphi и FreePascal для этих целей используется слово message, а для создания обычных динамических методов — слово dynamic), отличающиеся меньшим использованием памяти и меньшей скоростью вызова за счёт отсутствия дублирования динамических методов предков в VMT потомка (однако FreePascal не делает различий между виртуальными и динамическими методами).

В Delphi, FPC реализована перегрузка операций, абстрактные методы, директивы private, protected, public, published (по умолчанию члены класса являются public):

type

TbasicO = object

procedure writeByte (b:byte); virtual; abstract;

end;

 

TtextO =object (TbasicO) {наследует TbasicO, реализует остальные операции вывода на основе writeByte}

procedure writeS (s: string);

{..}

end;

 

TfileO = object (TbasicO) {класс файлового вывода - реализует операцию вывода как вывод байта в файл}

constructor init (n: string);

procedure writeByte (b: byte); virtual;

destructor closefile;

private

f: file of byte;

end;

 

basicO = ^TbasicO;

textO = ^TtextO;

fileO = ^TfileO;

 

constructor TfileO.init (n: string);

begin

assign (f, n);

rewrite (f)

end;

 

destructor TfileO.closefile;

begin

close (f)

end;

 

procedure TfileO.writeByte (b: byte);

begin

write (f, b)

end;

 

procedure TtextO.writeS (s: string);

var i: integer;

begin

for i:=1 to length(s) do

writeByte (ord(s[i]))

end;

{..}

 

var f: fileO;

begin

new (f, init('tstobj.txt')); {выделяет пямять под объект и вызывает конструктор}

textO(f)^.writeS ('text string');

dispose (f, closefile) {вызывает деструктор и освобождает память объекта}

end.

В диалекте Delphi классы могут также конструироваться с помощью слова class (причём взаимное наследование с object-классами не допускается) и введены интерфейсы (interface) — все методы абстрактные и не могут содержать полей данных.

Все классы (созданные с помощью class) являются наследниками TObject, все интерфейсы происходят от IUnknown. Классы, созданные с помощью class, могут реализовывать несколько интерфейсов.

В Delphi интерфейсы были введены для поддержки технологии COM фирмы Microsoft.

Классы (Class) в отличие от обычных классов (Object) не нуждаются в явном выделении/освобождении памяти, память под них динамически выделяется конструктором с именем Create, вызываемым с именем класса, и освобождается при вызове деструктора с именем Destroy (могут иметь другие имена). Переменная такого класса в отличие от класса object хранит адрес экземпляра класса в памяти, значение nil используется для указания пустой ссылки, поэтому для освобождения объекта в TObject определен специальный метод free, проверяющий ссылку на nil и вызывающий виртуальный деструктор Destroy. Код с использованием таких классов будет выглядеть следующим образом:

q1 := t1.create(9); { конструируем объект(t1 - имя класса) }

writeln (q1.InstanceSize); { вывод размера экземпляра класса }

q1.Free; { уничтожение объекта }

q1 := nil; { чтобы не происходило повторного вызова деструктора при вызове free }

В модификации ObjectPascal/Delphi/FreePascal в описании классов появляются свойства (property), которые совмещают удобство работы с переменными (роль которых в ООП играют поля) и вызовы методов, которые всегда уведомляют объект об изменении его состояния:

type

TMyObj=class(TObject)

FProp:integer;

procedure SetProp(AValue:integer);

property MyProp:integer read FProp write SetProp;

end;

procedure TMyObj.SetProp(AValue:integer);

begin

FProp:=AValue;

Writeln('Somebody has changed MyProp!');

end;

var MyObj:TMyObj;

begin

MyObj:=TMyObj.Create;

MyObj.FProp:=5;

MyObj.MyProp:=MyObj.MyProp+6;

end.

В первом случае (использование MyObj.FProp) поле объекта было изменено непосредственно, в итоге, методы объекта не будут подозревать, что это поле было ранее изменено; в более сложном случае они могут полагаться на то, что поле неизменно, либо же полю может быть присвоено значение, недопустимое для данного объекта. Во втором случае значение присваивается непосредственно свойству объекта, которое ссылается на вызов метода, корректно обрабатывающего изменение данного поля. Этот подход удобен, если объект связан с визуальным элементом: непосредственное изменение поля, отвечающего, например, за ширину элемента, никак не отразится на самом визуальном элементе, а объект будет «дезинформирован» относительно реальных размеров элемента. Корректным подходом без использования свойств является разработка методов на получение и установку любого значения поля, но работа с такими методами будет менее удобна, например, вместо последней строки надо было бы написать

MyObj.SetProp(MyObj.GetProp+6);

,

причём метод MyObj.GetProp следовало бы написать для унификации доступа. Большой интерес представляют индексные свойства, которые ведут себя практически так же, как и массивы, заменяя обращение к элементу массива вызовом соответствующего метода. Тем не менее, свойства не являются «панацеей»: при компиляции обращение к свойствам непосредственно транслируются в вызов методов или прямую работу с полями, поэтому настоящими переменными свойства не являются, в частности, их невозможно передавать в виде var-параметров.

 

 




Поиск по сайту:

©2015-2020 studopedya.ru Все права принадлежат авторам размещенных материалов.