ООП с примерами (часть 2) / Хабр

Инкапсуля́ция ( лат.in capsula) — размещение в оболочке, изоляция, закрытие чего-либо инородного с целью исключения влияния на окружающее. В информатике , программировании  — обеспечение доступности главного, выделение основного содержания путём помещения всего мешающего, второстепенного в некую условную капсулу ( чёрный ящик ).

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

Инкапсуляция (программирование)

Последнее осуществляется благодаря принципу изоляции решений разработки в ПО, известному как сокрытие информации (англ. information hiding ).

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

В объектно-ориентированных языках инкапсуляция, как правило, реализуется посредством механизма классов . Некоторые исследователи классифицируют инкапсуляцию как понятие, присущее исключительно объектно-ориентированному программированию , и необходимое для управления сокрытием , но существуют и другие механизмы, рассматривающие эти понятия независимо. Например, применение средств инкапсуляции для многих задач оказывается ненужным в языках, использующих лексическую область видимости , которая обеспечивает полное сокрытие компонентов. Примерами таких языков служат Scheme и Standard ML .

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

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

ИНКАПСУЛЯЦИЯ

ИНКАПСУЛЯЦИЯ (от лат-capsula—ящик, капсула, сумка), осумкование, термин, употребляющийся для обозначения разрастания соединительнотканной капсулы, сумки вокруг тех или иных пат. образований, паразитов и пр. тел, не подвергающихся почему-либо рассасыванию в обычном порядке. Так, И. могут подвергаться старые гнойники, а также творожистые массы при tbc, сифилисе; говорят об инкапсулированных паразитах, напр. трихинах, цистицерках и т. д. И. подвергаются также инородные тела, например внедрившиеся в ткань осколки металла, пули. Самое развитие капсулы идет по общим принципам развития отграничивающего (демаркационного) воспаления, образования пояса грануляционной ткани, которая в дальнейшем превращается в фиброзную, рубцо-вую капсулу, сумку; в некоторых случаях внутренние слои этой капсулы сохраняют весьма долго грануляционный характер (например, в осумкованных гнойниках), а иногда (напр. при И. паразитов, разных инородных тел)—многочисленные гигантские клетки. По существу процессы И. являются процессами организации и заживления, впрочем в условном смысле слова, т.

Значение слова инкапсуляция

к. инкапсулированные бактерии и паразиты, несмотря на значительную (многолетнюю) давность И., могут оставаться живыми и вирулентными, что представляет опасность как для носителя процесса (напр. реинфекция из инкапсулированного гнойника, из первичного очага при tbc легких), так и для других индивидов (например заражение трихинозом при употреблении мяса с инкапсулированными трихинами). Нередко в капсуле, а также и в содержимом ее наблюдают отложение известковых солей; реже в ткани капсулы в порядке метаплазии развивается костная ткань, как это нередко бывает с первичным туб. аффектом легких.

Смотрите также:
  • INCLUSIO FETALIS (лат.—плодное включение), уродство развития, заключающееся в том, что в полостях тела внешне правильно развитого плода («аутозита») обнаруживают отдельные части другого плода («паразита»); сюда относятся напр. нек-рые тератомы средостения, яичников, яичек …
  • INCONTINENTIA (лат.—недержание)^ер-мин, принятый для обозначения симптома непроизвольного опорожнения полостных органов, играющих роль резервуаров для выделений организма (моча, кал). Эти органы опорожняются в здоровом состоянии периодически, по мере накопления содержимого; их периодич. …
  • ИНКРУСТАЦИЯ (от латинск. incrustare— покрывать корой или слоем чего-нибудь), импрегнация (отлатинск. impregnare— наполнять, набивать чем-нибудь). Оба слова употребляются в одинаковом смысле для обозначения адсорпции каким-либо материалом в организме того или иного …
  • ИНКУБАЦИОННЫЙ ПЕРИОД, инкубация (от лат. incubare—возлегать), обозначение периода, отделяющего момент заражения от фазы явной реакции макроорганизма. Со времени открытия носительства, указывающего на то, что одного проникновения микроба еще недостаточно для заражения, …
  • ИННЕРВАЦИЯ, снабжение органов и тканей нервами. Различают центростремительные, или афферентные нервы, по которым раздражение приносится в центральную нервную систему, и центробежные, или эфферентные нервы, по которым передаются импульсы, идущие от …

к оглавлению   к алгоритмизации   СУБД   ЯиМП   3GL   4GL   5GL   технологии прогр.

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

Наследование в языке С++

Модификаторы наследования

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

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

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

При определении класса потомка за его именем следует разделитель-двоеточие (:), затем – необязательный модификатор наследования и имя родительского класса. Модификатор наследования определяет видимость наследуемых переменных и методов для пользователей и возможных потомков самого класса-потомка. Другими словами, он определяет, какие права доступа к переменным и методам класса-родителя будут «делегированы» классу-потомку. При реализации наследования, область «видимости» принадлежащих классу данных и методов можно определять выбором ключевого слова private (собственный), public (общедоступный) или protected (защищенный), которые могут произвольно чередоваться внутри описания класса. С двумя первыми модификаторами доступа мы уже знакомы, – private описывает закрытые члены класса, доступ к которым имеют только методы–члены этого класса, public предназначен для описания общедоступных элементов, доступ к которым возможен из любого места в программе. Особый интерес представляют элементы, обладающие модификатором доступа protected. Модификатор protected используется тогда, когда необходимо, чтобы некоторые члены базового класса оставались закрытыми, но были бы доступны для производного класса. Protected эквивалентен private с единственным исключением: защищенные члены базового класса доступны для членов всех производных классов этого базового класса.

То, как изменяется доступ к элементам базового класса из методов производного класса, в зависимости от значения модификаторов наследования, приведено в таблице.

    Модификатор наследования
Модификатор доступа public protected private
public public protected private
protected protected protected private
private нет доступа нет доступа нет доступа

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

Конструкторы и деструкторы при наследовании

Базовый класс, производный класс или оба могут иметь конструкторы и/или деструкторы.

Если и у базового и у производного классов есть конструкторы и деструкторы, то конструкторы выполняются в порядке наследования, а деструкторы – в обратном порядке. Т.е. если А базовый класс, В – производный из А, а С – производный из В (А-В-С), то при создании объекта класса С вызов конструкторов будет иметь следующий порядок: конструктор А — конструктор В — конструктор С. Вызов деструкторов при разрушении этого объекта произойдет в обратном порядке: деструктор С — деструктор В — деструктор А.

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

Эта программа выводит следующее

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

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

Допускается также, что конструктор базового класса может иметь больше параметров, чем конструктор производного класса.

Еще раз обратите внимание на то, что в расширенной форме объявления конструктора производного класса описывается вызов (!!!) конструктора базового класса.

Пример построения классов и наследования

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

Но пиксел на экране монитора, кроме координат своего положения, обладает еще и возможностью «светиться». Расширим структуру:

Тип Boolean хорошо знаком программистам на Паскале. Этот код использует перечисляемый тип enum для проверки true (истина) или false (ложь). Так как значения перечисляемого типа начинаются с 0, то Boolean может иметь одно из двух значений: 0 или 1 (ложь или истина).

Учитывая наш опыт работы со структурой _3d, мы должны позаботиться об интерфейсе класса Point. Нам будут необходимы методы для инициализации координат пикселя и указания, «включен» он или нет. Кроме того, если мы захотим сделать внутренние переменные недоступными, следует предоставить какой-либо способ узнать, что в них находится, прочитать их значения регламентированным образом. Следующая версия может выглядеть:

Теперь у нас есть возможность объявлять объекты типа :

Задание аргументов по умолчанию при описании прототипа конструктора дает нам возможность вызывать конструктор без аргументов или с неполным списком аргументов:

Пока мы может создавать объекты класса Point и определять их координаты, но не можем пока их показывать.

Так что необходимо дополнить класс Point соответствующими методами.

Теперь, когда у нас есть полноценный класс Point, можно создавать объекты–точки, высвечивать, гасить и перемещать их по экрану.

Если потребуется создать класс для другого графического объекта, то можно выбрать один из двух способов: либо начать его реализацию «с нуля», либо воспользоваться уже готовым классом Point, сделав его базовым. Второй способ кажется более предпочтительным, поскольку он предполагает использование уже готовых модулей, все, что при этом нужно – это создать новый производный от Point класс, дополнив его новыми состояниями и методами и/или переопределив некоторые методы базового класса.

Давайте попробуем создать класс Circle для окружности. Окружность, в известном смысле, является жирной точкой. Она имеет все, что имеет точка (позицию X и Y и видимое/невидимое состояние) плюс радиус. По-видимому, класс Circle появляется, чтобы иметь только отдельный элемент Radius, однако не забывайте обо всех элементах, которые наследует Circle, являясь классом, порожденным из Point. Circle имеет X, Y, а также Visible, даже если их не видно в определении класса для Circle.

Поскольку класс Circle – производный от класса Point, то, соответственно, класс Circle наследует из класса Point состояния X, Y, Visible, а также методы isVisible(), GetX(), GetY(). Что касается методов Show(), Hide() и MoveTo() класса Circle, то необходимость их переопределения продиктована спецификой объектов нового класса, поскольку, например, показать окружность, – это не то же самое, что показать точку.

Заметьте, что методы Circle требуют доступа к различным элементам данных в классах Circle и Point. Рассмотрим Circle::Expand. Она требует доступа к Radius. Нет проблем. Radius определен как private в самом Circle. Поэтому Radius доступен любой функции элементов из класса Circle.

Теперь рассмотрим Circle::Hide и Circle::Show. Они требуют доступа к Visible из своего базового класса Point. В этом примере Visible имела protected доступ в Point. А Circle порождается с доступом public из Point. Поэтому, Visible имеет protected доступ в пределах Circle. Заметим, что если бы Visible определялась как private в Point, то она была бы недоступна для функций элементов Circle. Можно было бы сделать Visible c доступом public. Однако в таком случае Visible сделалась бы доступной для функций не являющихся элементами.

Совместимость типов

Наследование предъявляет свои требования к правилам совместимости типов.

В добавление ко всему прочему, порожденный тип наследует совместимость со всеми типами предка.

Что такое инкапсуляция?

Эта расширенная совместимость имеет три формы:

  • между экземплярами объектов,
  • между указателями объектов,
  • между формальными и фактическими параметрами.

Однако во всех трех формах необходимо запомнить, что совместимость типов распространяется от потомка к предку. Другими словами, порожденные классы можно свободно использовать вместо классов предка, но не наоборот.

Например,

При наличии этих объявлений следующие присваивания являются законными:

Обратные присваивания незаконны.

Родительскому объекту можно присваивать объект любого порожденного им класса.

Чтобы было проще запомнить путь совместимости типов, давайте рассуждать таким образом:

1.

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

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

В предложениях присваивания будут копироваться только те поля, которые являются общими для обоих типов, то есть только поля предка.

Совместимость типов также действует между указателями на классы. Указатели на потомков можно присваивать указателям на предков по тем же общим правилам, как и для экземпляров объекта.

Формальный параметр объекта заданного класса может использовать в качестве фактического параметра объект такого же класса или любого порожденного класса. Например,

Тогда фактические параметры могут иметь тип Point, Circle и любой другой порожденный от них тип.

к оглавлению   к алгоритмизации   СУБД   ЯиМП   3GL   4GL   5GL   технологии прогр.

Знаете ли Вы, что абстракция — это процесс изменения уровня детализации программы. Когда мы абстрагируемся от проблемы, мы предполагаем игнорирование ряда подробностей с тем, чтобы свести задачу к более простой.
НОВОСТИ ФОРУМА
Рыцари теории эфира
 

Основные принципы ООП (инкапсуляция, полиморфизм, наследование).

⇐ Предыдущая15161718192021222324Следующая ⇒

ООП базируется на трех основных принципах: инкапсуляция, наследование, полиморфизм. Эти принципы ООП работают вместе и практически не существуют отдельно друг от друга.

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

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

Обычно стремятся инкапсулировать как можно большую часть класса.

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

Полиморфизм – это использование единого по названию метода, который по-разному реализован для различных родственных фаз.

 

Реализация ООП в Delphi (объявление и реализация классов, поля, методы и свойства, создание и уничтожение экземпляров классов, конструкторы и деструкторы).

 

Реализация ООП в Delphi (объявление и реализация классов, поля, методы и свойства, создание и уничтожение экземпляров объектов, конструкторы и деструкторы).

 

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

Для описания объектов служат классы. Каждый объект является экземпляром какого-либо класса.

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

Type

TInfo = class

FKey: Integer; // поле

procedureShow; // метод1

functionGetKey: Integer; // метод2

constructorCreate; // конструктор

destructorDestroy; // деструктор

end;

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

Обычно для реализации одного или нескольких классов используют отдельный модуль. Типы и переменные описывают в части interface, а реализация методов класса происходит в части implementation этого модуля.

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

Переменная объектного типа называется экземпляром класса или объектом:

Var

AMyObject: TInfo; // одна переменная

A: array[1..10] ofTInfo; // массив переменных

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

Для работы с переменной объектного типа недостаточно только ее описания. Инициализация переменной производится специальным методом, называемым конструктором:

AMyObject := TInfo.Create;

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

constructorTInfo.Create;

Begin

Fkey := -1;

end;

Конструктор – особый метод. Когда он вызывается, объекта еще не существует и при его вызове используется не имя переменной (как обычно), а имя класса. Конструктор – это метод класса (вызывается с помощью ссылки на класс). Вызов конструктора для создания экземпляра объекта называют созданием экземпляра. При создании экземпляра объекта с помощью конструктора все поля экземпляра будут инициализированы. Все числовые поля будут обнулены, указатели примут значение nil, а строки будут пусты.

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

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

Необходимо взять за правило – всегда уничтожать и освобождать все, что было создано в программе.

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

Свойства объекта (property) это специальные средства доступа к полям объекта, позволяющие изменять данные его полей и выполнять код его методов. Обычно свойство определяется тремя элементами: полем и двумя методами, которые осуществляют его чтение/запись:

Type

TMyClass = class

FKey: Integer;

functionGetKey: Integer;

procedureSetKey(constValue: Integer);

propertyKey: Integer readGetKey writeSetKey;

end;

Соответствующие реализации:

functionTMyClass.GetKey: Integer;

Begin

Result := FKey;

end;

procedureTMyClass.SetKey(constValue: Integer);

Begin

ifFkey <> ANewKey then

Begin

Fkey := ANewKey;

… // здесь могут выполняться дополнительные действия

end;

end;

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

Type

TMyClass = class

FKey: Integer;

procedureSetKey(constValue: Integer);

propertyKey: Integer readFKey writeSetKey;

end;

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

Type

TMyClass = class

FKey: Integer;

propertyKey: Integer readFKey;

end;

Попытка присвоить значение свойству вызовет ошибку компиляции.

 


⇐ Предыдущая15161718192021222324Следующая ⇒


Дата добавления: 2016-11-19; просмотров: 175 | Нарушение авторских прав


Похожая информация:


Поиск на сайте:


Инкапсуляция данных

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

Инкапсулированными являются не только данные, но и операции. Только часть операций является доступной снаружи и предоставляет интерфейс объекта.

Инкапсуляция, полиморфизм, наследование

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

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

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

Полиморфизм

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


Дата добавления: 2016-10-26; просмотров: 1085;


Похожие статьи:

Добавить комментарий

Закрыть меню