Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Объектно-ориентированный подход в программированииСтр 1 из 9Следующая ⇒
Объектно-ориентированный подход в программировании Ооп состоит в том, чтобы упростить задачу создания сложного программного обеспечения путем переноса в приложение сущностей и процессов, уже определенных в проблемной области, и применения полученных моделей для решения поставленной задачи. При объектно-ориентированном подходе программа представляет собой описание объектов, их свойств (или атрибутов), совокупностей (или классов), отношений между ними, способов их взаимодействия и операций над объектами (илиметодов). Несомненным преимуществом данного подхода является концептуальная близость к предметной области произвольной структуры и назначения. Механизм наследования атрибутов и методов позволяет строить производные понятия на основе базовых и таким образом создавать модель сколь угодно сложной предметной области с заданными свойствами. Еще одним теоретически интересным и практически важным свойством объектно-ориентированного подхода является поддержка механизма обработки событий, которые изменяют атрибуты объектов и моделируют их взаимодействие в предметной области. Использование ранее разработанных (возможно, другими коллективами программистов) библиотек объектов и методовпозволяет значительно сэкономить трудозатраты при производстве программного обеспечения, в особенности, типичного. Сложность адекватной (непротиворечивой и полной) формализации объектной теории порождает трудности тестирования и верификации созданного программного обеспечения. Пожалуй, это обстоятельство является одним из самых существенных недостатков объектно-ориентированного подхода к программированию.Поясним качественно фундаментальные принципы ООП. Наследование конкретных атрибутов объектов и функций оперирования объектами основано на иерархии. Инкапсуляция означает " сокрытие" свойств и методов внутри объекта. Полиморфизм, как и в функциональном программировании, понимается как наличие функций с возможностью обработки данных переменного типа. Ключевым понятием в оот явл объект. Объектом называется специальным образом оформленный фрагмент программы, заключающий в себе данные и подпрограммы для их обработки. Данные называются полями объекта, а подпрограммы – его методами. Объект в целом предназначен для решения какой-либо конкретной задачи и воспринимается в программе как неделимое целое. Два главных свойства объекта: функциональность и неделимость делают его самостоятельной и даже более того, самодостаточной частью программы и позволяют легко переносить объект из одной программы в другую. Разработчики 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 type var implementation procedure TForm1.FormCreate(Sender: TObject); 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 MODULE). В этой оболочке перечисляются объекты, экспортируемые из модуля, и специфици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. ТТРегsоп = class Все что объявлено в секции private, доступно только внутри модуля в котором объявлен класс (приватные объявления). Здесь как правило объявляются переменные, в которых хранятся значения свойств, а также методы (процедуры или функции) доступа к ним. Все что объявлено в секции protected, доступно как и в секции private, а также наследникам данного класса (интерфейс разработчика). Здесь можно объявить методы доступа к значениям свойств (если вы хотите позволить изменять эти методы потомкам вашего компенента), а также свойства, методы и события (методы реакции на события) в компонентах типа TCustomXXX. Популярное:
|
Последнее изменение этой страницы: 2016-07-14; Просмотров: 1773; Нарушение авторского права страницы