Light-electric.com

IT Журнал
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

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

Что такое ООП на примерах. Для чайников

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

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

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

Об объектах и классах

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

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

Одним из самых распространенных объектно-ориентированных языков программирования является язык java. Там без использования объектов просто не обойтись. Вот как будет выглядеть код класса, описывающего треугольник на этом языке:

Если мы внутрь класса добавим следующий код:

то программу уже можно будет запускать на выполнение. Это особенность языка java. Если в классе есть такой метод

то этот класс можно выполнять. Разберем код подробнее. Начнем со строки

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

выводят рассчитанные площадь треугольника и его периметр в консоль.

Аналогично все происходит и для второго экземпляра класса Triangle .

Понимание сути классов и конструирования конкретных объектов — это уверенный первый шаг к пониманию методологии ООП.

Еще раз, самое важное:

ООП — это способ организации кода программы;

Класс — это пользовательская структура данных, которая воедино объединяет данные и функции для работы с ними(поля класса и методы класса);

Объект — это конкретный экземпляр класса, полям которого заданы конкретные значения.

Три волшебных слова

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

Инкапсуляция — свойство системы, позволяющее объединить данные и методы, работающие с ними, в классе. Некоторые языки (например, С++) отождествляют инкапсуляцию с сокрытием, но большинство (Smalltalk, Eiffel, OCaml) различают эти понятия.

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

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

Понять, что же все эти определения означают на деле достаточно сложно. В специализированных книгах, раскрывающих данную тему на каждое определение, зачастую, отводится целая глава, но, как минимум, абзац. Хотя, сути того, что нужно понять и отпечатать навсегда в своем мозге программиста совсем немного.
А примером для разбора нам будут служить фигуры на плоскости. Из школьной геометрии мы знаем, что у всех фигур, описанных на плоскости, можно рассчитать периметр и площадь. Например, для точки оба параметра равны нулю. Для отрезка мы можем вычислить лишь периметр. А для квадрата, прямоугольника или треугольника — и то, и другое. Сейчас же мы опишем эту задачу в терминах ООП. Также не лишним будет уловить цепь рассуждений, которые выливаются в иерархию классов, которая , в свою очередь, воплощается в работающий код. Поехали:

Итак, точка — это самая малая геометрическая фигура, которая является основой всех прочих построений (фигур). Поэтому именно точка выбрана в качестве базового родительского класса. Напишем класс точки на java:

У получившегося класса Point пустой конструктор, поскольку в данном примере мы работаем без конкретных координат, а оперируем только параметрами значениями сторон. Так как у точки нет никаких сторон, то и передавать ей никаких параметров не надо. Также заметим, что класс имеет методы Point::getSquare() и Point::getPerimeter() для расчета площади и периметра, оба возвращают 0. Для точки оно и логично.

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

означает, что класс LineSegment наследуется от класса Point . Методы LineSegment::getSquare() и LineSegment::getPerimeter() переопределяют соответствующие методы базового класса. Площадь отрезка всегда равняется нулю, а площадь периметра равняется длине этого отрезка.

Теперь, подобно классу отрезка, опишем класс треугольника(который также наследуется от класса точки):

Тут нет ничего нового. Также, методы Triangle::getSquare() и Triangle::getPerimeter() переопределяют соответствующие методы базового класса.
Ну а теперь, собственно, тот самый код, который показывает волшебство полиморифзма и раскрывает мощь ООП:

Мы создали массив объектов класса Point , а поскольку классы LineSegment и Triangle наследуются от класса Point , то и их мы можем помещать в этот массив. Получается, каждую фигуру, которая есть в массиве figures мы можем рассматривать как объект класса Point . В этом и заключается полиморфизм: неизвестно, к какому именно классу принадлежат находящиеся в массиве figures объекты, но поскольку все объекты внутри этого массива принадлежат одному базовому классу Point , то все методы, которые применимы к классу Point также и применимы к его классам-наследникам.

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

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

Автор: Сергей Никонов

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

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

Объектно-ориентированное программирование (ООП) — это популярная парадигма программирования, пришедшая на смену процедурному подходу в программировании.

Процедурное программирование — это монолитная программа с набором инструкций для выполнения, с ветвлениями и подпрограммами.

Для понимания разницы между процедурным программированием и ООП программированием, я приведу примеры одного и того же кода в разных парадигмах.

Пример кода на PHP процедурного программирования:

Пример кода на PHP в объектно-ориентированном стиле программирования:

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

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

В том случае, если задача будет повторяться и постоянно меняться условия выполнения программы — лучше использовать объектно-ориентированное программирование.

Что такое класс (class)

Класс — это набор полей и методов программы. Рассмотрим прошлый пример. У нас есть класс Human:

Human — это имя класса.
$words — это поле класса (или переменная класса)
setWords, getWords(), sayIt() — это методы класса

Базовые принципы объектно-ориентированного программирования

Объектно-ориентированное программирование базируется на трех основных принципах. Это инкапсуляция, полиморфизм и наследование. На этих трех базовых принципах мы остановимся подробнее.

Для лучшего понимания я буду приводить примеры из реальных объектов в жизни. Это кстати одна из особенностей объектно-ориентированного программирования.

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

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

Для лучшего понимания, приведу пример инкапсуляции в жизни на примере телефона:

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

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

Пример инкапсуляции на примере класса Human:

В этом примере мы добавили в класс Human приватное поле пол ($sex). Ключевое слово private обозначает, что мы не сможем получить доступ к переменной $sex из вне класса.

Если мы попытаемся обратиться к полю $seх из вне класса, тогда мы получим ошибку:

$human->sex = «11»; Fatal error: Cannot access private property Human::$sex

Для того, чтобы задать поле пол, нам нужно обратиться к методу setSex() и передать ему в качестве параметра пол Human. В этом методе стоит проверка, male или female (мужчина или женщина).

Если в качестве параметра мы попробуем передать другой параметр в этот метод, например $human->setSex(“123″), тогда метод вернет нам ошибку.

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

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

Что такое наследование

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

Пример наследования из жизни очень простой:

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

За вами тянется целая эволюционная цепочка генов, начиная с генов древних предков обезьян, заканчивая генами современного человека — вашими родителями. В объектно-ориентированном программирование, наследование тоже самое свойство.

Читать еще:  Наследование в программировании

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

Наследование в объектно-ориентированном программированием обозначается ключевым словом extends. Давайте изменим класс Human и применив наследование ООП, создадим классы мужчины и женщины.

В результате выполнения программы, мы увидим следующее:

Меня зовут Sergey и у меня растет борода

Меня зовут Maria и я рожаю детей

В этом примере, классы Мужчина и Женщина унаследовали от родительского класса Human общий метод say(), то есть, и Мужчина и Женщина у нас умеют говорить, но для Мужчины и Женщины, мы ввели свои особенности: У мужчины растет борода, а женщина умеет рожать детей.

Метод под названием __construct — это конструктор класса. Что такое конструктор класса, читайте в статье.

Что такое полиморфизм

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

Пример полиморфизма из жизни:

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

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

Если полиморфизм перенести на пример с классами — то это общий метод для объектов.

Давайте посмотрим на примере реализацию полиморфизма в PHP:

В результате выполнения программы, мы увидим следующее:

У меня мужской голос, меня зовут Sergey и у меня растет борода
У меня женский голос, меня зовут Maria и я рожаю детей

Мы модифицировали наши прошлые классы и добавили такие понятия объектно-ориентированного программирования как Интерфейс и Абстрактный класс.

Обратите внимание, что метод say() в классах Man и Women мы реализуем по-разному. Это и есть полиморфизм.

Что такое интерфейс в ООП

Интерфейс — это шаблонный класс без реализации. То есть в интерфейсе мы только задаем методы и эти методы обязаны реализовать классы.

В нашем прошлом примере наш интерфейс Say с единственным методом say():

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

Что такое абстрактный класс в ООП

Абстрактный класс в ООП — это класс шаблонный класс от которого нельзя создать экземпляр класса.

Это значит, что мы не можем с абстрактным классом сделать так:

$human = new Human(«name»);

Если мы попытаемся создать экземпляр абстрактного класса, интерпретатор PHP выдаст ошибку.

Абстрактный класс мы можем только наследовать. Взгляните еще раз на абстракный класс. Перед классом он содержит ключевое слово abstract. Также он имплементирует интерфейс Say (implements).

Выводы о ООП

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

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

В следущих статьях мы поговорим о таких ключевых словах как public, private, protected, static и рассмотрим еще примеры. Если у вас остались вопросы, пишите комментарии и мы обязательно попробуем вам подсказать решение.

Вступайте в нашу группу VK и следите за новыми материалами.

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

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

В данном уроке мы рассмотрим классы в C++ и познакомимся с объектно-ориентированным программированием. Объектно-ориентированное программирование или ООП — это одна из парадигм программирования. Парадигма — это, другими словами, стиль. Парадигма определяет какие средства используются при написании программы. В ООП используются классы и объекты. Все наши предыдущие программы имели элементы разных парадигм: императивной, процедурной, структурной.

Мы можем написать одинаковую программу в разных парадигмах. Парадигмы не имеют чёткого определения и часто пересекаются.

Давайте посмотрим на пример. Допустим, в нашей игре есть танки и они могут стрелять, при стрельбе у них уменьшается боезапас. Как мы можем это смоделировать без ООП:

У нас есть структура, которая содержит поле, представляющее количество снарядов, и есть функция атаки, в которую мы передаём танк. Внутри функции мы меняем количество снарядов. Так может выглядеть игра на языке C: структуры отдельно от функций, которые совершают действия со структурными переменными. Данную ситуацию можно смоделировать по-другому с помощью объектно-ориентированного программирования (Object-Oriented Programming, OOP) — ООП.В ООП действия привязываются к объектам.

Определение классов в C++

Класс — это пользовательский тип данных (также как и структуры). Т.е. тип данных, который вы создаёте сами. Для этого вы пишете определение класса. Определение класса состоит из заголовка и тела. В заголовке ставится ключевое слов class, затем имя класса (стандартный идентификатор C++). Тело помещается в фигурные скобки. В C++ классы и структуры почти идентичны. В языке C в структурах можно хранить только данные, но в C++ в них можно добавить действия.

В C++ ключевые слова struct и class очень близки и могут использоваться взаимозаменяемо. У них есть только одно отличие (об этом ниже). Вот как можно определить такой же класс с помощью struct:

Отличие только первом ключевом слове. В одном из прошлых уроков мы уже обсуждали структуры. что мы видим новое? Ключевые слова private и public — это спецификаторы доступа. Также мы видим, что внутри класса мы можем вставлять определения функций.

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

Переменные и методы класса

Класс состоит из членов класса (class members). Члены класса могут быть переменными (data members) или методами (function members или methods). Переменные класса могут иметь любой тип данных (включая другие структуры и классы). Методы — это действия, которые может выполнять класс. По сути, это обычные функции.

Все методы класса имеют доступ к переменным класса. Обратите внимание, как мы обращаемся к ammo в методе Attack.

Создание объектов класса

Теперь у нас есть свой тип данных и мы можем создавать переменные данного типа. Если после определения структур мы могли создавать структурные переменные, то в случае классов, мы создаём объекты классов (или экземпляры). Разница между классами и структурами только в терминах. Для C++ это почти одно и то же.

Вот так мы можем создать объекты класса Tank и вызвать метод Attack:

t1 и t2 — объекты класса Tank. Для C++ объект класса — это всего-лишь переменная. Тип данных этих переменных — Tank. Ещё раз повторю, что классы (и структуры) позволяют создавать пользовательские типы данных.

В англоязычной литературе создание объектов классов также называется созданием экземпляров — instantiating.

Мы обращаемся к переменным класса и методам с помощью оператора точки (прямой доступ), также как мы обращались к полям структурных переменных.

В нашем примере каждый объект имеет доступ к своей копии ammo. ammo — переменная класса (data member). Attack — метод класса. У каждого объекта своя копия переменных класса, но все объекты одного класса вызывают одни и те же методы.

Размер объекта включает все данные, но не методы

В памяти переменные класса располагаются последовательно. Благодаря этому мы можем создавать массивы объектов и копировать их все вместе (если в классе этих объектов нет динамического выделения памяти). Это будет важно для нас, когда мы начнём работать с графикой в DirectX/OpenGL. Размер объекта класса можно узнать с помощью функции sizeof. При этом в качестве аргумента можно использовать как объект, так и сам класс:

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

Указатель this

Вот как для компилятора выглядит любой метод:

Это просто иллюстрация. В реальности не нужно указывать аргумент (всё что в круглых скобках). Мы автоматически получаем доступ к указателю this. В данном случае его использование перед ammo необязательно, компилятор автоматически привяжет эту переменную к this.

Указатель this нужен, когда методу необходимо вернуть указатель на текущий объект.

Указатели на объекты

При работе с объектам в C++ вам неизбежно придётся работать с указателями (и ссылками). Как мы помним, при передаче в функцию по значению создаётся копия переменной. Если у вас сложный класс, содержащий большой массив или указатели, то копирование такого объекта может потребовать ненужное выделение дополнительной памяти или может быть вообще невозможным, в случае если в классе вы динамически выделяете память. Поэтому очень часто объекты создаются динамически. Для доступа к таким объектам используется оператор непрямого доступа (стрелочка):

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

Чуть ниже мы увидим один случай, когда не обойтись без ссылок.

Конструктор класса (Constructor)

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

Здесь, в конструкторе задаются начальные значения переменных, но мы можем делать в нём всё что угодно, это обычная функция.

Перегрузка конструктора класса

Перегрузка (overloading) конструктора позволяет создать несколько конструкторов для одного класса с разными параметрами. Всё то же самое, что и при перегрузке функций:

Начальные значения можно задавать в виде списка инициализации. Выше в конструкторе мы инициализировали переменные внутри тела. Список инициализации идёт перед телом конструктора и выглядит так:

В списке инициализации можно задать значение только части переменных класса.

Копирующий конструктор (Copy Constructor)

Без каких-либо действий с нашей стороны мы можем присваивать объектам другие объекты:

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

В копирующем конструкторе всегда используются ссылки. Это обязательно. Параметр point — это объект, стоящий справа от оператора присваивания.

Деструктор класса

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

Допустим в нашем танке есть экипаж, пусть это будет один объект типа Unit. При создании танка мы выделяем память под экипаж. В деструкторе нам нужно будет освободить память:

Имя деструктора совпадает с именем класса и перед ним ставится тильда

. Деструктор может быть только один.

Объектно-ориентированное программирование в C++ (ООП)

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

Читать еще:  Программирование с нуля c для чайников

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

Что означает слово Encapsulation? Корень — капсула. En — предлог в. Инкапсуляция — это буквально помещение в капсулу. Что помещается в капсулу? Данные и действия над ними: переменные и функции. Инкапсуляция — связывание данных и функций. Давайте ещё раз взглянем на класс Tank:

Собственно, здесь в класс Tank мы поместили переменную ammo и метод Attack. В методе Attack мы изменяем ammo. Это и есть инкапсуляция: члены класса (данные и методы) в одном месте.

В C++ есть ещё одно понятие, которое связано с инкапсуляцией — сокрытие данных. Сокрытие предполагает помещение данных (переменных класса) в область, в которой они не будут видимы в других частях программы. Для сокрытия используются спецификаторы доступа (access specifiers). Ключевые слова public и private и есть спецификаторы доступа. public говорит, что весь следующий блок будет видим за пределами определения класса. private говорит, что только методы класса имеют доступ к данным блока. Пример:

Здесь мы видим, что объект может получить доступ только к членам класса, находящимся в блоке public. При попытке обратиться к членам класса (и переменным, и методам) блока private, компилятор выдаст ошибку. При этом внутри любого метода класса мы можем обращаться к членам блока private. В методе Move мы изменяем скрытые переменные x и y.

Хороший стиль программирования в ООП предполагает сокрытие всех данных. Как тогда задавать значения скрытых данных и получать доступ к ним? Для этого используются методы setters и getters.

Setters and Getters

Setters и Getters сложно красиво перевести на русский. В своих уроках я буду использовать английские обозначения для них. Setter (set — установить) — это метод, который устанавливает значение переменной класса. Getter (get — получить) — метод, который возвращает значение переменной:

Имена не обязательно должны включать Set и Get. Использование setters и getters приводит к увеличению количества кода. Можно ли обойтись без инкапсуляции и объявить все данные в блоке public? Да, можно. Но данная экономия кода имеет свои негативные последствия. Мы будем подробно обсуждать данный вопрос, когда будем говорить об интерфейсах.

Следующая концепция ООП — наследование.

Наследование (Inheritance) в C++

Производный класс не может получить доступ к private членам. Поэтому в классе Unit используется спецификатор protected. Данный спецификатор разрешает доступ к данным внутри класса и внутри дочерних классов, private же разрешает доступ только в методах самого класса.

При наследовании производный класс имеет доступ ко всем членам (public и protected) базового класса. Именно поэтому мы можем вызвать метод Move для объекта типа Archer.

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

Полиморфизм (Polymorphism)

Наследование открывает доступ к полиморфизму. Poly — много, morph — форма. Это очень мощная техника, которую мы будем использовать постоянно.

Полиморфизм позволяет поместить в массив разные типы данных:

Мы создали массив указателей на Unit. Но C++ позволяет поместить в такой указатель и указатель на любой дочерний классс. Данная техника будет особенно полезна, когда мы изучим виртуальные функции.

Заключение

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

В следующем уроке мы познакомимся с более сложными концепциями, касающимися классов: виртуалье методы, шаблоны, статичные члены. Впоследствии мы увидим, как классы используютя в DirectX.

Единственное отличие между классом и структурой в C++: по умолчанию в структуре используется спецификатор доступа public, а в классе — private. Часто в коде вы будете видеть, что структуры используются без методов, чисто для описания каких-либо сущностей. Но это делать необязательно это всего лишь соглашение.

Объектно-ориентированное программирование: на пальцах

Ста­тья не маль­чи­ка, но мужа.

Наста­ло вре­мя серьёз­ных тем: сего­дня рас­ска­жем про объектно-ориентированное про­грам­ми­ро­ва­ние, или ООП. Это тема для про­дви­ну­то­го уров­ня раз­ра­бот­ки, и мы хотим, что­бы вы его постиг­ли.

Из это­го тер­ми­на мож­но сде­лать вывод, что ООП — это такой под­ход к про­грам­ми­ро­ва­нию, где на пер­вом месте сто­ят объ­ек­ты. На самом деле там всё немно­го слож­нее, но мы до это­го ещё добе­рём­ся. Для нача­ла пого­во­рим про ООП вооб­ще и раз­бе­рём, с чего оно начи­на­ет­ся.

Обычное программирование (процедурное)

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

Напри­мер, в интернет-магазине может быть функ­ция «Про­ве­рить email». Она полу­ча­ет на вход какой-то текст, сопо­став­ля­ет со сво­и­ми пра­ви­ла­ми и выда­ёт ответ: это пра­виль­ный элек­трон­ный адрес или нет. Если пра­виль­ный, то true, если нет — то false.

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

Что не так с процедурным программированием

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

Напри­мер, вы пише­те функ­цию «Заре­ги­стри­ро­вать поль­зо­ва­те­ля интернет-магазина». Внут­ри неё вам нуж­но про­ве­рить его элек­трон­ный адрес. Вы вызы­ва­е­те функ­цию «Про­ве­рить email» внут­ри функ­ции «Заре­ги­стри­ро­вать поль­зо­ва­те­ля», и в зави­си­мо­сти от отве­та функ­ции вы либо реги­стри­ру­е­те поль­зо­ва­те­ля, либо выво­ди­те ошиб­ку. И у вас эта функ­ция встре­ча­ет­ся ещё в деся­ти местах. Функ­ции как бы пере­пле­те­ны.

Тут при­хо­дит продакт-менеджер и гово­рит: «Хочу, что­бы поль­зо­ва­тель точ­но знал, в чём ошиб­ка при вво­де элек­трон­но­го адре­са». Теперь вам нуж­но научить функ­цию выда­вать не про­сто true — false, а ещё и код ошиб­ки: напри­мер, если в адре­се опе­чат­ка, то код 01, если адрес спа­мер­ский — код 02 и так далее. Это неслож­но реа­ли­зо­вать.

Вы зале­за­е­те внутрь этой функ­ции и меня­е­те её пове­де­ние: теперь она вме­сто true — false выда­ёт код ошиб­ки, а если ошиб­ки нет — пишет «ОК».

И тут ваш код лома­ет­ся: все десять мест, кото­рые ожи­да­ли от про­ве­ряль­щи­ка true или false, теперь полу­ча­ют «ОК» и из-за это­го лома­ют­ся.

Теперь вам нуж­но:

  • либо пере­пи­сы­вать все функ­ции, что­бы научить их пони­мать новые отве­ты про­ве­ряль­щи­ка адре­сов;
  • либо пере­де­лать сам про­ве­ряль­щик адре­сов, что­бы он остал­ся сов­ме­сти­мым со ста­ры­ми места­ми, но в нуж­ном вам месте как-то ещё выда­вал коды оши­бок;
  • либо напи­сать новый про­ве­ряль­щик, кото­рый выда­ёт коды оши­бок, а в ста­рых местах исполь­зо­вать ста­рый про­ве­ряль­щик.

Зада­ча, конеч­но, реша­е­мая за час-другой.

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

Это назы­ва­ет­ся спагетти-код, и для борь­бы с ним как раз при­ду­ма­ли объектно-ориентированное про­грам­ми­ро­ва­ние.

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

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

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

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

Объ­ект мож­но пред­ста­вить как неза­ви­си­мый элек­тро­при­бор у вас на кухне. Чай­ник кипя­тит воду, пли­та гре­ет, блен­дер взби­ва­ет, мясо­руб­ка дела­ет фарш. Внут­ри каж­до­го устрой­ства куча все­го: мото­ры, кон­трол­ле­ры, кноп­ки, пру­жи­ны, предо­хра­ни­те­ли — но вы о них не дума­е­те. Вы нажи­ма­е­те кноп­ки на пане­ли каж­до­го при­бо­ра, и он дела­ет то, что от него ожи­да­ет­ся. И бла­го­да­ря сов­мест­ной рабо­те этих при­бо­ров у вас полу­ча­ет­ся ужин.

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

Инкап­су­ля­ция — объ­ект неза­ви­сим: каж­дый объ­ект устро­ен так, что нуж­ные для него дан­ные живут внут­ри это­го объ­ек­та, а не где-то сна­ру­жи в про­грам­ме. Напри­мер, если у меня есть объ­ект «Поль­зо­ва­тель», то у меня в нём будут все дан­ные о поль­зо­ва­те­ле: и имя, и адрес, и всё осталь­ное. И в нём же будут мето­ды «Про­ве­рить адрес» или «Под­пи­сать на рас­сыл­ку».

Абстрак­ция — у объ­ек­та есть «интер­фейс»: у объ­ек­та есть мето­ды и свой­ства, к кото­рым мы можем обра­тить­ся извне это­го объ­ек­та. Так же, как мы можем нажать кноп­ку на блен­де­ре. У блен­де­ра есть мно­го все­го внут­ри, что застав­ля­ет его рабо­тать, но на глав­ной пане­ли есть толь­ко кноп­ка. Вот эта кноп­ка и есть абстракт­ный интер­фейс.

В про­грам­ме мы можем ска­зать: «Уда­лить поль­зо­ва­те­ля». На язы­ке ООП это будет «пользователь.удалить()» — то есть мы обра­ща­ем­ся к объ­ек­ту «поль­зо­ва­тель» и вызы­ва­ем метод «уда­лить». Кайф в том, что нам не так важ­но, как имен­но будет про­ис­хо­дить уда­ле­ние: ООП поз­во­ля­ет нам не думать об этом в момент обра­ще­ния.

Напри­мер, над мага­зи­ном рабо­та­ют два про­грам­ми­ста: один пишет модуль зака­за, а вто­рой — модуль достав­ки. У пер­во­го в объ­ек­те «заказ» есть метод «отме­нить». И вот вто­ро­му нуж­но из-за достав­ки отме­нить заказ. И он спо­кой­но пишет: «заказ.отменить()». Ему неваж­но, как дру­гой про­грам­мист будет реа­ли­зо­вы­вать отме­ну: какие он отпра­вит пись­ма, что запи­шет в базу дан­ных, какие выве­дет пре­ду­пре­жде­ния.

Насле­до­ва­ние — спо­соб­ность к копи­ро­ва­нию. ООП поз­во­ля­ет созда­вать мно­го объ­ек­тов по обра­зу и подо­бию дру­го­го объ­ек­та. Это поз­во­ля­ет не копи­па­стить код по две­сти раз, а один раз нор­маль­но напи­сать и потом мно­го раз исполь­зо­вать.

Напри­мер, у вас может быть некий иде­аль­ный объ­ект «Поль­зо­ва­тель»: в нём вы про­пи­сы­ва­е­те всё, что может про­ис­хо­дить с поль­зо­ва­те­лем. У вас могут быть свой­ства: имя, воз­раст, адрес, номер кар­ты. И могут быть мето­ды «Дать скид­ку», «Про­ве­рить заказ», «Най­ти зака­зы», «Позво­нить».

На осно­ве это­го иде­аль­но­го поль­зо­ва­те­ля вы може­те создать реаль­но­го «Поку­па­те­ля Ива­на». У него при созда­нии будут все свой­ства и мето­ды, кото­рые вы зада­ли у иде­аль­но­го поку­па­те­ля, плюс могут быть какие-то свои, если захо­ти­те.

Иде­аль­ные объ­ек­ты про­грам­ми­сты назы­ва­ют клас­са­ми.

Поли­мор­физм — еди­ный язык обще­ния. В ООП важ­но, что­бы все объ­ек­ты обща­лись друг с дру­гом на понят­ном им язы­ке. И если у раз­ных объ­ек­тов есть метод «Уда­лить», то он дол­жен делать имен­но это и писать­ся вез­де оди­на­ко­во. Нель­зя, что­бы у одно­го объ­ек­та это было «Уда­лить», а у дру­го­го «Сте­реть».

При этом внут­ри объ­ек­та мето­ды могут быть реа­ли­зо­ва­ны по-разному. Напри­мер, уда­лить товар — это выдать пре­ду­пре­жде­ние, а потом поме­тить товар в базе дан­ных как уда­лён­ный. А уда­лить поль­зо­ва­те­ля — это отме­нить его покуп­ки, отпи­сать от рас­сыл­ки и заар­хи­ви­ро­вать исто­рию его поку­пок. Собы­тия раз­ные, но для про­грам­ми­ста это неваж­но. У него про­сто есть метод «Уда­лить()», и он ему дове­ря­ет.

Читать еще:  Программирование на visual basic

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

Плюсы и минусы ООП

У объектно-ориентированного про­грам­ми­ро­ва­ния мно­го плю­сов, и имен­но поэто­му этот под­ход исполь­зу­ет боль­шин­ство совре­мен­ных про­грам­ми­стов.

  • Визу­аль­но код ста­но­вит­ся про­ще, и его лег­че читать. Когда всё раз­би­то на объ­ек­ты и у них есть понят­ный набор пра­вил, мож­но сра­зу понять, за что отве­ча­ет каж­дый объ­ект и из чего он состо­ит.
  • Мень­ше оди­на­ко­во­го кода. Если в обыч­ном про­грам­ми­ро­ва­нии одна функ­ция счи­та­ет повто­ря­ю­щи­е­ся сим­во­лы в одно­мер­ном мас­си­ве, а дру­гая — в дву­мер­ном, то у них боль­шая часть кода будет оди­на­ко­вой. В ООП это реша­ет­ся насле­до­ва­ни­ем.
  • Слож­ные про­грам­мы пишут­ся про­ще. Каж­дую боль­шую про­грам­му мож­но раз­ло­жить на несколь­ко бло­ков, сде­лать им мини­маль­ное напол­не­ние, а потом раз за разом подроб­но напол­нить каж­дый блок.
  • Уве­ли­чи­ва­ет­ся ско­рость напи­са­ния. На стар­те мож­но быст­ро создать нуж­ные ком­по­нен­ты внут­ри про­грам­мы, что­бы полу­чить мини­маль­но рабо­та­ю­щий про­то­тип.

А теперь про мину­сы:

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

Что дальше

Впе­ре­ди нас ждёт раз­го­вор о клас­сах, объ­ек­тах и всём осталь­ном важ­ном в ООП. Кре­пи­тесь, будет инте­рес­но!

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

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

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

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

Примером объектно-ориентированных языков являются: Object Pascal, C++, Java.

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

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

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

Объект состоит из следующих трех частей:

— состояние (переменные состояния);

Каждый объект является представителем (экземпляром) определенного класса. Во время выполнения программы объекты взаимодействуют друг с другом, вызывая методы, которые являются подпрограммами, характерными для определённого класса.

Класс (class) – это группа данных и методов (функций) для работы с этими данными. Это шаблон. Объекты с одинаковыми свойствами, то есть с одинаковыми наборами переменных состояния и методов, образуют класс. Объект (object) – это конкретная реализация, экземпляр класса. В программировании отношения объекта и класса можно сравнить с описанием переменной, где сама переменная (объект) является экземпляром какого-либо типа данных (класса).

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

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

Практический подход. В современных объектно-ориентированных языках программирования (php, Java, C++, Oberon, Python, Ruby, Smalltalk, Object Pascal) создание класса сводится к написанию некоторой структуры, содержащей набор полей и методов. Практически класс может пониматься как некий шаблон, по которому создаются объекты — экземпляры данного класса. Экземпляры одного класса созданы по одному шаблону, поэтому имеют один и тот же набор полей и методов.

Отношения между классами:

— Наследование (Генерализация) — объекты дочернего класса наследуют все свойства родительского класса.

— Ассоциация — объекты классов вступают во взаимодействие между собой.

— Агрегация — объекты одного класса входят в объекты другого.

— Композиция — объекты одного класса входят в объекты другого и зависят друг от друга по времени жизни.

— Класс-Метакласс — отношение, при котором экземплярами одного класса являются другие классы.

Виды классов:

— базовый (родительский) класс;

— производный класс (наследник, потомок);

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

Методы – инкапсулированные в классе процедуры и функции, то есть способы работы с данными.

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

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

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

Цели инкапсуляции:

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

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

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

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

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

Суть инкапсуляции: Переменные состояния объекта скрыты от внешнего мира. Изменение состояния объекта (его переменных) возможно ТОЛЬКО с помощью его методов (операций). Почему это так важно? Этот принцип позволяет защитить переменные состояния объекта от неправильного их использования.

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

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

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

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

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

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

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

Для реализации таких иерархий в языке программирования предусмотрен полиморфизм. Слово полиморфизм имеет греческое происхождение и переводится как «имеющий много форм».

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

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

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

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

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

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

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

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

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

Механизм работы ООП в таких случаях можно описать примерно так: при вызове того или иного метода класса сначала ищется метод у самого класса. Если метод найден, то он выполняется и поиск этого метода на этом завершается. Если же метод не найден, то обращаемся к родительскому классу и ищем вызванный метод у него. Если найден – поступаем как при нахождении метода в самом классе. А если нет – продолжаем дальнейший поиск вверх по иерархическому дереву. Вплоть до корня (верхнего класса) иерархии.

Ссылка на основную публикацию
Adblock
detector