Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


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



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

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

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

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

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

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

В ооп используется важное понятие «класс». Классом в Delphi называются функционально законченные фрагменты программ, служащие образцами для создания подобных себе экземпляров. Однажды создав класс, программист может включать его экземпляры в разные программы или в разные места одной и той же программы. В состав Delphi входит несколько сотен классов, так называемых стандартных классов. Совокупность стандартных классов определяет мощные возможности этой системы программирования.

Каждый компонент принадлежит к строго определенному классу, а все конкретные экземпляры компонентов, вставляемые в форму, получают имя класса с добавленным числовым индексом.

Класс является образцом, по которому создаются объекты, и наоборот, объект – это экземпляр реализации класса.

В ооп как классы так и объекты включают в себя поля свойства методы и события.

Поля как члены классы служат для хранения данных, содержащихся в объекте. Поля аналогичны переменным.

Свойство( property. ) — способ доступа к внутреннему состоянию объекта, имитирующий переменную некоторого типа.

Методами называют действия которые объект может выполнить.

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

 

Базовые понятия ООП

Абстракция

Абстрагирование — это способ выделить набор значимых характеристик объекта, исключая из рассмотрения незначимые. Соответственно, абстракция — это набор всех таких характеристик.[1]

Инкапсуляция

Инкапсуляция — это свойство системы, позволяющее объединить данные и методы, работающие с ними в классе, и скрыть детали реализации от пользователя.[1]

Наследование

Наследование — это свойство системы, позволяющее описать новый класс на основе уже существующего с частично или полностью заимствующейся функциональностью. Класс, от которого производится наследование, называется базовым, родительским или суперклассом. Новый класс — потомком, наследником или производным классом.[1]

Полиморфизм

Полиморфизм — это свойство системы использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта.

 

Понятие класса и объекта

Объектом называется специальным образом оформленный фрагмент программы, заключающий в себе данные и подпрограммы для их обработки. Данные называются полями объекта, а подпрограммы – его методами. Объект в целом предназначен для решения какой-либо конкретной задачи и воспринимается в программе как неделимое целое. Два главных свойства объекта: функциональность и неделимость делают его самостоятельной и даже более того, самодостаточной частью программы и позволяют легко переносить объект из одной программы в другую. Разработчики Delphi создали сотни объектов для программистов, которые можно рассматривать как кирпичики, из которых он строит многоэтажное здание программы.

Познакомимся еще с одним важным понятием в Delphi «класс». Классом в Delphi называются функционально законченные фрагменты программ, служащие образцами для создания подобных себе экземпляров. Однажды создав класс, программист может включать его экземпляры в разные программы или в разные места одной и той же программы. В состав Delphi входит несколько сотен классов, так называемых стандартных классов. Совокупность стандартных классов определяет мощные возможности этой системы программирования.

Каждый компонент принадлежит к строго определенному классу, а все конкретные экземпляры компонентов, вставляемые в форму, получают имя класса с добавленным числовым индексом.

По используемому в Delphi соглашению все имена классов начинаются с буквы T. Так имя TForm1 означает имя класса, созданного по образцу стандартного класса TForm.

Строка

TForm1 =class (TForm)

определяет новый класс TForm1, который порожден от (создан по образцу от) стандартного класса TForm. Строка

Form1: TForm1;

создает экземпляр этого класса – объект с именем Form1.

Стандартный класс TForm описывает пустое Windows окно, в то время как класс TForm1 описывает окно с уже вставленными в него компонентами. Описание этих компонентов содержат строки:

Button1: TButton;

Label1: TLabel;

Они указывают, что компонент Button1 представляет экземпляр - объект стандартного класса TButton, а компонент Label1 – экземпляр – объект класса TLabel.

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

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

Классом в Object Pascal называется структура языка, которая может иметь в своем составе переменные, функции и процедуры. Переменные в зависимости от предназначения именуются полями или свойствами (см. ниже). Процедуры и функции класса — методами. Соответствующий классу тип будем называть объектным типом:

type

TMyObject = class(TObject)

MyField: Integer;

function MyMethod: Integer;

end;

В этом примере описан класс TMyObject, содержащий поле MyField и метод

MyMethod.

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

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

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

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

Разрешено опережающее объявление классов, как в следующем примере:

type

TFirstObject = class;

TSecondObject = class(TObject)

Fist: TFirstObject;

...

end;

TFirstObject = class(TObject)

...

end;

Чтобы использовать класс в программе, нужно, как минимум, объявить переменную этого типа. Переменная объектного типа называется экземпляром класса или объектом:

var

AMyObject: TMyObject;

До введения термина " класс" в языке Pascal существовала двусмысленность определения " объект", который мог обозначать и тип, и переменную этого типа. Теперь же существует четкая граница: класс — это описание, объект — то, что создано в соответствии с этим описанием.

Как создаются и уничтожаются объекты?

Те, кто раньше использовал ООП в работе на C++ и особенно в Turbo Pascal, будьте внимательны: в Object Pascal экземпляры объектов могут быть только динамическими. Это означает, что в приведенном выше фрагменте переменная AMyObject на самом деле является указателем, содержащим адрес объекта.

Объект " появляется на свет" в результате вызова специального метода, который инициализирует объект — конструктора. Созданный экземпляр уничтожается другим методом — деструктором:

AMyObject: = TMyObject.Create;

{ действия с созданным объектом }

...

AMyObject.Destroy;

Но, скажет внимательный читатель, ведь объекта еще нет, как мы можем вызывать его методы? Справедливое замечание. Однако обратите внимание, что вызывается метод TMyObject.Create, а не AMyObject.Create. Есть такие методы (в том числе конструктор), которые успешно работают до (или даже без) создания объекта. О подобных методах, называемых методами класса, пойдет речь чуть ниже.

В Object Pascal конструкторов у класса может быть несколько. Общепринято называть конструктор create (в отличие от Turbo Pascal, где конструктор обычно назывался init, и от C++, где его имя совпадает с именем класса). Типичное название деструктора — Destroy.

type

TMyObject = class(TObject)

MyField: Integer;

Constructor Create;

Destructor Destroy;

Function MyMethod: Integer;

end;

Для уничтожения экземпляра объекта рекомендуется использовать метод Free, который первоначально проверяет указатель (не равен ли он Nil) и только затем вызывает Destroy:

AMyObj ect.Free;

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

Примечание

Конструктор создает новый объект только в том случае, если перед его именем указано имя класса. Если указать имя уже существующего объекта, он поведет себя по-другому: не создаст новый объект, а только выполнит код, содержащийся в теле конструктора.

Чтобы правильно инициализировать в создаваемом объекте поля, относящиеся к классу-предку, нужно сразу же при входе в конструктор вызвать конструктор предка при помощи зарезервированного слова inherited:

constructor TMyObject.Create;

begin

inherited Create;

...

end;

Взяв любой из примеров, прилагаемых к этой книге или поставляемых вместе в Delphi, вы почти не увидите там вызовов конструкторов и деструкторов. Дело в том, что любой компонент, попавший при визуальном проектировании в ваше приложение из Палитры компонентов, включается в определенную иерархию. Иерархия эта замыкается на форме (класс TForm): для всех ее составных частей конструкторы и деструкторы вызываются автоматически, незримо для программиста. Кто создает и уничтожает формы? Это делает приложение (глобальный объект с именем Application). В файле проекта (с расширением dpr) вы можете увидеть вызовы метода Application.CreateForm, предназначенного для этой цели.

Что же касается объектов, создаваемых динамически (во время выполнения приложения), то здесь нужен явный вызов конструктора и метода Free.

Класс (class) – это структура, объединяющая данные и механизмы обработки этих данных в единое целое.

В терминах языка Delphi классы также называют типами.

Экземпляр класса (или типа) называется объектом, т.е. можно создать любое количество объектов одного класса.

Класс – это тип данных, а объект – это конкретный, существующий в памяти компьютера, экземпляр класса, переменная соответствующего типа.

Классы состоят из следующих 3 частей.

1. Поля(Fields)– характеристики объекта (как тип данных Record)

2. Свойства (Properties) – напоминают поля, но имеющие дополнительные описатели, определяющие механизмы записи и считывания данных

3. Методы (Methods) - подпрограммы, которые обрабатывают поля и свойства классов.

Фактически класс отражает реальные, и даже абстрактные понятия окружающего мира.

Поля, свойства и методы называются членами класса.

Описание класса в Delphi

Новый класс описывается в Delphi в разделе описания типов:

type имя_класса = class (имя_родительского_класса)

< поле 1>;

< поле n>;

< метод 1>;

< метод n>;

end;

Описание полей и свойств в классе должно предшествовать описанию методов.

 

Пример объявления простого класса «Человек», имеющего поля: имя, адрес.

type Tperson = class (TObject)

fname: string; {поле «имя»}

faddress: string; {поле «адрес»}

procedure NewAddress (newaddress: string); {метод изменения адреса}

procedure Show; { метод, который выводит на экран значения полей}

end;

 

 

Interface

uses
Forms, Dialogs, Classes, Controls, StdCtrls, Windows;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;

var
Form1: TForm1;

implementation
{$R *.dfm} // Вложение определений формы

procedure TForm1.FormCreate(Sender: TObject);
begin
// Использование Self для идентификации формы позволяя нам
// установить некоторые атрибуты формы
Self. Caption: = 'Test program';
Self. Visible: = True;
end;

End.

Перегруженные методы

Начиная с 4-й версии Delphi, Object Pascal предусматривает возможность работы с одноименными функциями, имеющими различные списки параметров.

Механизм перегрузки методов позволяет вам иметь несколько одноименных процедур или функций с различными списками параметров.

Методы, имеющие общее имя, называются перегруженными.

Раньше мы уже рассматривали программу, содержавшую функцию Multiply. Эта функция принимала в качестве параметров два целых числа и после их перемножения возвращала результат. Но что, если вам потребуется функция, перемножающая два числа типа Double или Word? В предыдущих версиях Delphi вам пришлось бы создать несколько функций:

{ объявления в программе, написанной в Delphi 1, 2 или 3}

function Multiplylnt(Num1, Num2: Integer): Integer;

function MultiplyDouble(Num1, Num2: Double): Double;

function MultiplyWord(Num1, Num2: Word): Word;

Не проще ли иметь только одну функцию Multiply, достаточно сообразительную для того, чтобы самой определить, числа какого типа (integer, Double или Word) вы хотите перемножить? Благодаря перегрузке функций в Delphi 4 появилась такая возможность. Вот как выглядят объявления перегруженной функции:

{ объявления в Delphi 4}

function Multiply(Num1, Num2: Integer): Integer; overload;

function Multiply(Num1, Num2: Double): Double; overload;

function Multiply(Num1, Num2: Word): Word; overload;

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

var

X, Y, Z: Double;

begin

X: = 1.5;

Y: = 10.5;

Z: = Multiply(X, Y); end;

Компилятор видит, что в функцию Multiply передаются два числа типа Double, и поэтому он вызывает ту версию функции Multiply, которая принимает два параметра типа Double. Точно так же, если бы были переданы два числа типа integer, он вызвал бы соответствующую версию с двумя параметрами типа Integer.

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

function DoSornething: Integer; overload;

function DoSomething: Word; overload;

Если вы попытаетесь компилировать этот код, то получите сообщение об ошибке Declaration of 'DoSomething' differs from previous declaration (объявление функции 'DoSomething' отличается от ее предыдущего объявления) Чтобы две функции можно было считать перегруженными, они должны отличаться не только возвращаемыми значениями

 

Инкапсуляция

Инкапсуляция – это принцип ООП, объединяющий в одном классе данные и методы, манипулирующие этими данными и защищающие данные класса от внешнего воздействия.

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

Класс также защищает свое состояние (значения свойств) от несанкционированного изменения, это реализуется с помощью раздела класса private. Включенные в privateсвойства доступны только этому объекту, поэтому не могут быть изменены другими объектами. Для доступа к свойствам в раздел класса public включаются методы. Методы проверяют, возможно ли такое изменение состояния объекта под влиянием других объектов, и только после этого изменяют значения переменных состояния. Если переход в новое состояние невозможен, методы оставляют объект в прежнем состоянии.

В языках программирования инкапсуля́ ция имеет одно из следующих значений, либо их комбинацию:

· языковой механизм ограничения доступа к определённым компонентам объекта;

· языковая конструкция, способствующая объединению данных с методами (или другими функциями), обрабатывающими эти данные.

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

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

Сокрытие реализации целесообразно применять в следующих целях:

· предельная локализация изменений при необходимости таких изменений,

· прогнозируемость изменений (какие изменения в коде нужно сделать для заданного изменения функциональности) и прогнозируемость последствий изменений.

В Delphi для создания скрытых полей или методов их достаточно объявить в секции private.

TMyClass = class

Private

FMyField: Integer;

procedure SetMyField( const Value: Integer );

function GetMyField: Integer;

Protected

Public

property MyField: Integer read GetMyField write SetMyField;

end;

Для создания интерфейса доступа к скрытым полям в Delphi введены свойства.

Инкапсуляция и модули

Инкапсуляция - одна из специфических особенностей прог­рамми­рова­ния, ориентированного на объекты. Эта особенность пред­пола­га­ет не только возможности " разложения целого на части" (прин­ци­па, определяющего основы любого программирования), но и умения " скры­вать" частности от общегo (целого). Такой подход позволяет про­г­раммисту не знать частных деталей реализации програмной сис­те­мы, осуществлять конструирование из элементов, реализация ко­то­­рых скрыта от него " под оболочкой" модуля. Модуль в этом под­хо­де приобретает роль основного конструктивного элемента, ис­поль­зуемого для синтеза и разработки новых систем.

Специфические особенности модуля заключаются в следующем:

1) модуль - это автономно компилируемая програмная единица;

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

3) сборка програмной системы из модулей связана с отдельным тех­нологическим этапом - компоновкой (линковкой) программы. Пра­ви­ла такой компоновки полностью определяются системой модульных оболочек.

Концепция оболочки реализуется декларациями импорта/экспорта, регламентирующими, какие объекты, определенные внутри модуля, мож­но использовать " за его пределами". Подобные декларации могут быть оформлены в разных видах. В Модуле-2, например, для этого ис­пользуется специальный вид описания модуля - так называемая спе­цифицирующая оболочка (оболочка опpеделений, DEFINITION MO­DU­LE). В этой оболочке пере­числяются объекты, экспортируемые из мо­дуля, и спе­ци­фи­ци­pу­ют­ся методы их использования (фак­тичес­ки, действия над объектами). Пpичем, спецификация пpоцедуpных мето­дов пpо­во­дит­ся на уpовне пpогpаммиста, использующего мо­дуль (пот­­­pеби­теля), котоpому пpедставляются только заголовки пpоцедуp для pаботы с экспоpтиpуемыми объектами, но не пpогpаммы их pеа­ли­за­ции. Напpимеp:

DEFINITION MODULE A;

EXPORT QUALIFIED B, C, D;

TYPE B;

VAR C: B;

PROCEDURE D(C: B);

END A.

В этом примере разрешено использование " за пределами" модуля A трех определенных в нем програмных объектов: типа В, пере­мен­ной С и процедуры D.

Концепция модуля как програмного эквивалента класса объектов пpедполагает использование его как определителя собственной (ин­­ди­ви­ду­аль­ной) алгебры: множества возможных объектов и дей­ст­вий над ни­ми. Такая концепция подразумевает, что в модуле опре­де­ля­ет­ся абстрактный тип и методы - процедуры, манипулирующие с объ­ек­тами этого типа. При этом стиль программирования, ориен­ти­ро­ван­ного на объекты, рекомендует экспортировать за пределы модуля только тип и процедуры - создание объектов этого типа должно производиться вне модуля - экспортеpа. Предыдущий пример в этом от­ношении нарушает такой стиль, разрешая экспорт переменной C.

Подобные стилевые особенности экспорта определяются сле­ду­ю­щи­ми соображениями. Ведь переменная C в приведенном примере - соб­ственная (внутренняя) переменная модуля A, размещенная в его ста­тической памяти. Можно ли менять значение этой переменной за пределами модуля? Или это не соответствует общим " житейским" пред­ставлениям об экспорте? И вообще, что можно делать с пе­ре­мен­ной C за пределами модуля? Если что угодно, то какой смысл за­­водить C в модуле А? Если действия над C внутpи A рег­ла­мен­ти­ро­ваны процедурами A, то целесообразно экспортировать только та­кой регламент, т.е. процедуры. В любом случае переменная, оп­ре­де­ленная в одном модуле и используемая в другом, приобретает ха­рак­тер разделяемой переменной - с ней могут работать программы, определенные в различных модулях и, возможно, написанные разными людьми. Конечно, существуют ситуации, когда от такого экспорта не­­возможно или нецелесообразно отказываться, но, согласитесь, что в некоторых случаях он может быть похож на экспорт станков, которые используются как металлолом.

Для идентификации " своих" и " чужих" объектов (принадлежащих дру­гому модулю) могут использоваться две формы импорта/экспорта: квалифицированный и неквалифицированный. Первая форма связана с ис­пользованием ключевого слова QUALIFIED в предложении экспорта и позволяет обращаться к экспортируемым объектам только по их " вну­треннему" имени, без префиксации именем модуля-экспортера. Вторая форма не требует использования этого ключевого слова, но корректная идентификация экспортируемых объектов в этом случае всегда связана с префиксацией. Например, для использования пе­ре­мен­ной C за пределами специфицирующей оболочки, определенной вы­ше для модуля A, в случае квалифицированного экспорта достаточно простого именования C, а при неквалифицированном экспорте свя­за­но с использованием префиксированного имени A.C.

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

Закрытый экс­порт запрещает использование каких-либо операций над экс­пор­ти­руемыми объектами кроме тех, которые определены в модуле-экс­пор­теpе. В этом смысле закрытый экспорт - это " экспорт сырья", " пот­­ребительских продуктов" и т.п.

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

DEFINITION MODULE SINCHRON;

EXPORT QUALIFIED SIGNAL, SEND, WAIT;

TYPE SIGNAL;

PROCEDURE SEND (VAR S: SIGNAL);

PROCEDURE WAIT (VAR S: SIGNAL);

END SINCHRON.

Закрытость экспорта в этом модуле позволяет его рассматривать как полностью инкапсулиpованное определение абстрактного типа (ал­гебры) синхpонизиpущих сигналов. Все имманентные свойства объ­ектов-сигналов скрыты от пользователя (в реализующей оболочке модуля - IMPLEMENTATION) и лишь два метода (SEND и WAIT) вы­не­се­ны на экспорт. Закрытость экспорта разрешает над любыми сиг­на­ла­ми, определенными вне SINCHRON, выполнение только двух действий: SEND и WAIT; использование для этого каких-либо других процедур и/или опе­раторов языка невозможно.

Реализующие определения и имманентные свойства класса SIGNAL, оп­ределенные в модуле IMPLEMENTATION, уточняют определение сиг­на­ла SIGNAL = POINTER TO PASPORT (см. pазд.VII) и определяют все де­тали работы с объектами этого типа.

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

----

---------> --+ A ¦

¦ LTTT-

¦ -----> ----¦L---< ----

¦ --+- --^- --+-

¦ ¦ B ¦ ¦ C +--> --+ D ¦

¦ L-T-- LT-T- L-T--

¦ ¦ ¦ ¦ ¦

¦ --+- ¦ ¦ ¦

L-+ E +--> ---- ¦ ¦

L-T-- ¦ ¦

L----< -----+---------

-----^---

¦ SYSTEM ¦

L---------

Здесь главный модуль A использует модули B, C, D, E и системный мо­дуль SYSTEM. Стpелки показывают напpавление экспоpта пpогpам­м­ных объектов, инкапсулиpованных в соответствующих модулях. Стpу­к­туpа связей на этой иллюстpации хаpактеpизуется наличием ба­зо­вых модулей (из них стpелки только выходят), модулей веpхнего уpо­в­ня (он здесь один - A), в котоpые стpелки только входят, пу­тей между базовыми и веpхними модулями (SYSTEM-C-A), (SYSTEM-C-D-A), (SYSTEM-C-D-E-B-A и т.д.) и петель (C-D-E-C).

Несмотpя на то, что наличие петель, вообще говоpя, не явля­ет­ся фатальным пpи компоновке модели A из модулей нижних уpовней, тем не менее " pазвязка" таких петель связана с некотоpыми пpоб­ле­мами. Pеализационно и технологически они pешаются коppектным кон­стpуиpованием последовательности деклаpаций импоpта в модуле A. Методологически же любая петля отpажает некачественную де­ком­по­зицию задачи, непpодуманную иеpаpхию понятий и методов, свя­зан­ных с ее pешением. В этом плане лучшая схема импоpта-экспоpта дол­жна основываться на выделении пpогpаммных слоев, начиная с ба­зового уpовня и кончая веpхним, пpедметно-оpиентиpованным па­ке­том пpикладных пpогpамм. Пpи этом напpавление стpелок экспоpта должно быть только снизу-ввеpх от базового слоя к веpхним и, pа­­­зумеется, петли должны быть исключены.

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

Заключение

Объектно-оpиентиpованный подход к pазpаботке пpогpамм и свя­зан­­ный с ним стиль пpогpаммиpования, оpиентиpованный на объекты, основаны на концепции абстpагиpования типов. Модуль как пpо­г­pам­м­ный эквивалент класса объектов, инкапсулиpующий в себе опpе­де­ле­ние такого абстpактного типа, является в этом отношении той кон­­стpуктивной единицей в объектно-оpиентиpованном подходе, ко­то­­pая позволяет совеpшить естественный пеpеход от тpадиционного пpо­цедуpного пpогpаммиpования к констpуиpованию пакетов пpи­к­лад­ных пpогpамм путем их послойной pазpаботки и отладки.

Данное пособие, посвященное отдельным аспектам объектно-оpиентиpованного подхода, пpеследует фактически одну цель - сфоp­­­миpовать у читателя общее пpедставление о паpадигме абс­тpа­ги­­pования, используя для этого пpед­ста­вле­­­ния и теpминологию объектно-оpиентиpованного подхода к pаз­pа­бот­ке пpогpамм. По­со­бие, pазумеется, не исчеpпывает всех воп­pо­сов и не освещает всех тонкостей пpогpаммиpования, оpи­ен­ти­pо­ван­но­го на объекты. Более то­го, пpи написании этого пособия автоp умышленно не оpиен­ти­pо­вал­ся на конкpетный объектно-оpиен­тиpо­ван­ный язык (напpимеp, Smalltalk). Такой подход опpеделяется тем, что специфика pе­а­ли­за­ции, теpминологии и методологии исполь­зо­ва­ния конкpетного язы­ка всегда затушевывает интуитивные, аб­ст­pак­т­ные начала в пpо­цес­се pазpаботки пpогpамм, отpывает пользователя от пpивычных ка­те­го­pий пpогpаммиpования и тем самым по­pож­дает некотоpый пси­холо­ги­ческий баpьеp, а поpою и непpиятие но­­вого подхода. В этом смы­сле автоp считал для себя важным " сломать" такой баpьеp, показав читателю, что интуитивно легко ощущаемая категоpия объекта яв­ля­ет­ся абсолютно естественной для пpогpаммиpования, " впитывает" в себя все аспекты пpоцесса стpуктуpизации и в этом плане ло­ги­чес­ки pазвивает и дополняет обы­ч­ное пpоцедуpное пpогpаммиpование но­выми сpедствами абс­тpа­ги­pо­вания.

Пpоцесс абстpагиpования является неотъемлемой частью ло­гичес­ко­­го мышления, и в этом отношении его pазвитие не имеет гpаниц, как и pазвитие пpоцесса познания вообще. Pеализация такого pазвития на ос­­­нове использования ЭВМ обеспечивает пpи этом не только (и не столь­ко) новые возможности пpогpаммиpования, сколько новые воз­мо­ж­ности моделиpования сложных объектов pеального миpа.

Директивы видимости

 

Помимо объявлений элементов класса (полей, методов, свойств) описание класса, как правило, содержит несколько директив, которые устанавливают степень видимости элементов класса в программе.Рассмотрим семантику директив видимости.1. Директива private.
Поля, свойства и методы, описанные в разделе private, называются личными или закрытыми. Сюда помещаются элементы (чаще всего поля), которые выполняют в объекте специфичные функции и которые поэтому целесообразно скрыть от других частей программы, либо такие элементы, для которых по ряду причин не следует разрешать доступ извне объекта.2. Директива public.
Элементы, описанные в разделе public, называются общедоступными. Они могут быть использованы всюду в программе. Поля, свойства и методы, расположенные сразу после заголовка класса, при выключенной директиве компилятора {$M-}, по умолчанию принимаются общедоступными.3. Директива protected.
Элементы класса, объявленные в разделе protected (защищенный), доступны только в классах, порожденных от исходного. Здесь размещаются элементы, которые важны лишь для функционирования объектов данного класса и его потомков. Обычно в секцию protected помещаются описания методов класса.4. Директива published.
Поля, свойства и методы, описанные в разделе published, называются опубликованными. Их область видимости эквивалентна области видимости общедоступных описаний. Отличие состоит в том, что информация о них, за исключением ряда типов, например real, на этапе проектирования программы помещается в инспектор объектов. Описания, расположенные сразу после заголовка класса, при включенной директиве компилятора {$M+}, по умолчанию принимаются опубликованными.
5. Директива automated.
Элементы класса, объявленные в разделе automated, называются автоматическими. Их область видимости эквивалентна области видимости общедоступных описаний. Отличие состоит в том, что для автоматических свойств и методов генерируется дополнительная информация, которая используется для реализацииOLE-механизма. Использовать директиву automated имеет смысл при объявлении потомков стандартного класса TAutoObject.
Ниже приведено описание класса TTPerson, в которое включены директивы видимости.

ТТРегsоп = class
private
FName: TName; { значение свойства Name }
FAddress: TAddress; ( значение свойства Address}
protected
Constructor Create(Name: TName);
Function GetName: TName;
Function GetAddress: TAddress;
Procedure SetAddress (NewAddress: TAddress);
Property Name: TName
read GetName;
Property Address: TAddress
read GetAddress
write SetAddress;
end;

Все что объявлено в секции private, доступно только внутри модуля в котором объявлен класс (приватные объявления). Здесь как правило объявляются переменные, в которых хранятся значения свойств, а также методы (процедуры или функции) доступа к ним.

Все что объявлено в секции protected, доступно как и в секции private, а также наследникам данного класса (интерфейс разработчика). Здесь можно объявить методы доступа к значениям свойств (если вы хотите позволить изменять эти методы потомкам вашего компенента), а также свойства, методы и события (методы реакции на события) в компонентах типа TCustomXXX.


Поделиться:



Популярное:

Последнее изменение этой страницы: 2016-07-14; Просмотров: 1654; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.137 с.)
Главная | Случайная страница | Обратная связь