Полиморфизм ооп простыми словами. Полиморфизм - что это? Генетический полиморфизм

Полиморфизм (программирование)

Кратко смысл полиморфизма можно выразить фразой: «Один интерфейс , множество реализаций».

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

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

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

Примеры

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

В функциональных языках

В Haskell существует два вида полиморфизма - параметрический (чистый) и специальный, (на основе классов ). Специальный называют еще ad hoc (от лат. ad hoc - специально). Их можно отличить следующим образом:

Параметрический полиморфизм

Специальный полиморфизм

В Haskell есть деление на классы и экземпляры (instance), которого нет в ООП . Класс определяет набор и сигнатуры методов (возможно, задавая для некоторых или всех из них реализации по умолчанию), а экземпляры реализуют их. Таким образом, автоматически отпадает проблема множественного наследования. Классы не наследуют и не переопределяют методы других классов - каждый метод принадлежит только одному классу. Такой подход проще, чем сложная схема взаимоотношений классов в ООП. Некоторый тип данных может принадлежать нескольким классам; класс может требовать, чтобы каждый его тип обязательно принадлежал к другому классу, или даже нескольким; такое же требование может выдвигать экземпляр. Это аналоги множественного наследования. Есть и некоторые свойства, не имеющие аналогов в ООП. Например, реализация списка, как экземпляра класса сравнимых величин, требует, чтобы элементы списка также принадлежали к классу сравнимых величин.

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

Неявная типизация

В некоторых языках программирования (например, в Python и Ruby) применяется так называемая утиная типизация (другие названия: латентная, неявная), которая представляет собой разновидность сигнатурного полиморфизма. Таким образом, например, в языке Python полиморфизм не обязательно связан с наследованием.

Формы полиморфизма

Статический и динамический полиморфизм

(упоминается в классической книге Саттера и Александреску, которая является источником).

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

В одном случае конкретный смысл фрагмента зависит от того, в каком окружении код был построен. Это т.н. статический полиморфизм. Перегрузка функций, шаблоны в Си++ реализуют именно статический полиморфизм. Если в коде шаблонного класса вызвана, например, std::sort, то реальный смысл вызова зависит от того, для каких именно типовых параметров будет развернут данный шаблон - вызовется одна из std::sort.

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

Полиморфизм включения

Этот полиморфизм называют чистым полиморфизмом. Применяя такую форму полиморфизма, родственные объекты можно использовать обобщенно. С помощью замещения и полиморфизма включения можно написать один метод для работы со всеми типами объектов TPerson. Используя полиморфизм включения и замещения можно работать с любым объектом, который проходит тест «is-A». Полиморфизм включения упрощает работу по добавлению к программе новых подтипов, так как не нужно добавлять конкретный метод для каждого нового типа, можно использовать уже существующий, только изменив в нем поведение системы. С помощью полиморфизма можно повторно использовать базовый класс; использовать любого потомка или методы, которые использует базовый класс.

Параметрический полиморфизм

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

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

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

Параметрические типы

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

Полиморфизм переопределения

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

Полиморфизм-перегрузка

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

Сравнение полиморфизма в функциональном и объектно-ориентированном программировании

Система классов в ФП и в ООП устроены по-разному, поэтому к их сравнению следует подходить очень осторожно.

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

Несмотря на концептуальные различия систем классов в ФП и ООП, реализуются они примерно одинаково - с помощью таблиц виртуальных методов .Используется часто в Java.

См. также

Ссылки

Примечания


Wikimedia Foundation . 2010 .

Смотреть что такое "Полиморфизм (программирование)" в других словарях:

    У этого термина существуют и другие значения, см. Полиморфизм. Полиморфизм компьютерного вируса (греч. πολυ много + греч. μορφή форма, внешний вид) специальная техника, используемая авторами вредоносного программного… … Википедия

    В объектно ориентированном программировании способность объекта выбирать правильный метод в зависимости от типа данных, полученных в сообщении. По английски: Polymorphism См. также: Объектно ориентированное программирование Финансовый словарь… … Финансовый словарь

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

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

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

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

В различных полиморфных модификациях существуют углерод, кремний, фосфор, железо и другие элементы. Физические свойства различных модификаций одного и того же вещества могут значительно отличаться. Например модификации углерода, кристаллизующиеся в виде алмаза (кубическая сингония) или в виде графита (гексагональная сингония), резко отличаются друг от друга по физическим свойствам, несмотря на идентичность состава. Если полиморфное превращение сопровождается незначительными изменениями структуры, физические свойства вещества изменяются несущественно. Полиморфных модификаций у каждого конкретного вещества должна быть две, три и более. Различные модификации принято обозначать греческими буквами α, β, γ и т.д., причем первые буквы, как правило, относятся к модификациям, устойчивым при более высоких температурах.

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

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

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

α ↔ β↔жидкость

т.е. перход α → β энантиотропен. Примерами энантиотропных полиморфных превращений являются превращения между полиморфными формами SiO 2 ˸

Полиморфизм - понятие и виды. Классификация и особенности категории "Полиморфизм" 2015, 2017-2018.

  • - Полиморфизм индивидов

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


  • - Дизруптивный благоприятствует сохранению крайних типов и элиминации промежуточных. Приводит к сохранению и усилению полиморфизма.

  • - Внутривидовая дифференцировка человечества. Расы как выражение генетического полиморфизма человечества. Видовое единство человечества.

    ВНУТРИВИДОВАЯ ДИФФЕРЕНЦИАЦИЯ ЧЕЛОВЕЧЕСТВА: С момента возникновения Н. sapiens социальное в человеке стало его сущностью и биологическая эволюция видоизменялась, проявляясь в возникновении широкого генетического полиморфизма. Генетическое разнообразие на уровне... .


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

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

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

    В соответствии с UML ( Unified Modelling Language - унифицированный язык моделирования ), класс имеет следующее графическое представление .

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

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

    • конструктор (constructor) - выполняется при создании объектов ;
    • деструктор ( destructor ) - выполняется при уничтожении объектов .

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

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

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

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

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

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

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

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

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

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

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

    В качестве примера можно рассмотреть задачу, в которой необходимо реализовать классы "Легковой автомобиль" и "Грузовой автомобиль". Очевидно, эти два класса имеют общую функциональность. Так, оба они имеют 4 колеса, двигатель, могут перемещаться и т.д. Всеми этими свойствами обладает любой автомобиль, независимо от того, грузовой он или легковой, 5- или 12-местный. Разумно вынести эти общие свойства и функциональность в отдельный класс , например, "Автомобиль" и наследовать от него классы "Легковой автомобиль" и "Грузовой автомобиль", чтобы избежать повторного написания одного и того же кода в разных классах .


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

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

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

    Все животные в зоомагазине являются наследниками класса "Животное", а также наследниками класса "Товар". Т.е. все они имеют возраст, нуждаются в пище и воде и в то же время имеют цену и могут быть проданы.

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

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

    В языке Java множественное наследование имеет ограниченную поддержку через интерфейсы и будет рассмотрено в лекции 8.

    Полиморфизм

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

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

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

    ... //создание пустого массива, который может // содержать объекты Point с максимальным // объемом 1000 Point p = new Point; Line l = new Line; Circle c = new Circle; Box b = new Box; ... // предположим, в этом месте происходит // заполнение всех массивов соответствующими // объектами... for(int i = 0; i < p.length;i++) { //цикл с перебором всех ячеек массива. //вызов метода draw() в случае, // если ячейка не пустая. if(p[i]!=null) p[i].draw(); } for(int i = 0; i < l.length;i++) { if(l[i]!=null) l[i].draw(); } for(int i = 0; i < c.length;i++) { if(c[i]!=null) c[i].draw(); } for(int i = 0; i < b.length;i++) { if(b[i]!=null) b[i].draw(); } ...

    Недостатком написанного выше кода является дублирование практически идентичного кода для отображения каждого типа примитивов. Также неудобно то, что при дальнейшей модернизации нашего графического редактора и добавлении возможности рисовать новые типы графических примитивов, например Text , Star и т.д., при таком подходе придется менять существующий код и добавлять в него определения новых массивов, а также обработку содержащихся в них элементов.

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

    Привет! Это статья об одном из принципов ООП - полиморфизм.

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

    Определение полиморфизма звучит устрашающе 🙂

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

    Слово "полиморфизм " может показаться сложным - но это не так. Нужно просто разбить данное определение на части и показать на примерах, что имеется в виду. Поверьте, уже в конце статьи данное определение полиморфизма покажется Вам понятным 🙂

    Полиморфизм , если перевести, - это значит "много форм". Например, актер в театре может примерять на себя много ролей - или принимать "много форм".

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

    Так о каких формах идет речь? Давайте сначала приведем примеры и покажем, как на практике проявляется полиморфизм, а потом снова вернемся к его определению.

    Как проявляется полиморфизм

    Дело в том, что если бы в Java не было принципа полиморфизма , компилятор бы интерпретировал это как ошибку:

    Как видите, методы на картинке отличаются значениями, которые они принимают:

    • первый принимает int
    • а второй принимает String

    Однако, поскольку в Java используется принцип полиморфизма, компилятор не будет воспринимать это как ошибку, потому что такие методы будут считаться разными :

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

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

    Теперь Вы можете понять, почему часто этот принцип описывают фразой:

    Один интерфейс - много методов

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

    Перегрузка методов

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

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

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

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

    Пример

    Представим, что у нас есть такая структура:

    Вверху иерархии классов стоит класс Animal . Его наследуют три класса - Cat , Dog и Cow .

    У класса "Animal" есть метод "голос" (voice). Этот метод выводит на экран сообщение "Голос". Естественно, ни собака, ни кошка не говорят "Голос" 🙂 Они гавкают и мяукают. Соответственно, Вам нужно задать другой метод для классов Cat , Dog и Cow - чтобы кошка мяукала, собака гавкала, а корова говорила "Муу".

    Поэтому, в классах-наследниках мы переопределяем метод voice() , чтобы мы в консоли получали "Мяу", "Гав" и "Муу".

    • Обратите внимание: перед методом, который мы переопределяем, пишем "@Override ". Это дает понять компилятору, что мы хотим переопределить метод.

    Так что же такое полиморфизм

    Тем не менее, полиморфизм - это принцип. Все реальные примеры, которые мы приведодили выше - это только способы реализации полиморфизма.

    Давайте снова посмотрим на определение, которое мы давали в начале статьи:

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

    Выглядит понятнее, правда? Мы показали, как можно:

    • создавать "одноименные методы" в одном классе ("перегрузка методов")
    • или изменить поведение методов родительского класса ("переопределение методов").

    Все это - проявления "повышенной гибкости" объектно-ориентированных языков благодаря полиморфизму.

    Надеемся, наша статья была Вам полезна. Записаться на наши курсы по Java можно у нас на .

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

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

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

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

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

    Приведем другой пример. Принципы инкапсуляции как скрытия внутренней реализации заложены в любой функции PHP. Возможно, вам уже известна функция strpos() для работы со строками из стандартной библиотеки PHP. Эта функция ищет в строке заданную последовательность символов и возвращает ее позицию в виде числа. Если задуматься над реализацией этой функции, то можно предположить, что нам потребуется в цикле просматривать каждый символ от начала строки на совпадение с начальным символом искомой последовательности и в случае такового сравнивать следующие два символа и т. д. Но нам как программистам нет необходимости задумываться над этим и вникать в тонкости реализации данной функции. Нам достаточно знать параметры , которые она принимает, и формат возвращаемого значения . Функция strpos() инкапсулирует в себе решение задачи поиска подстроки, предлагая нам лишь внешний интерфейс для ее использования.

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

    В языке PHP концепция инкапсуляции реализована в виде специальных модификаторов доступа к полям и методам классов. Об этом мы поговорим далее.

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

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

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

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

    Это значит, что в классах Квадрат и Треугольник нам не придется повторно задавать поля цвета и площади. Достаточно указать, что упомянутые классы наследуются от класса Фигура.

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

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

    Чтобы реализовать эту ситуацию в PHP, нам потребуется определить два класса: класс для обычной статьи-заметки и класс для новостной статьи. При этом пусть новостная статья расширяет возможности обычной статьи, т. е. наследуется от нее. Для наследования классов в PHP используется ключевое слово extends .

    Class { ... // содержимое класса } class { ... // содержимое класса }

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

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


    Иногда у нас может появиться необходимость переопределить один из методов родительского класса. Давайте еще раз приведем реализацию класса Article :

    Class Article { ... // поля класса // Функция для вывода статьи function view() { echo "

    $this->title

    $this->content

    "; } }

    Предположим, что вывод новостной статьи должен отличаться от представления обычной статьи, и мы должны дополнительно выводить время публикации новости. При этом в классе Article уже существует метод view() , отвечающий за вывод статьи. Можно поступить двумя способами. В первом случае можно придумать новый метод в классе NewsArticle , например, с именем viewNews() специально для вывода новости. Однако правильнее использовать одинаковые методы для выполнения схожих действий в наследуемых классах. Поэтому будет лучше, если метод для вывода новости в классе NewsArticle будет называться так же, как и в родительском классе - view() . Для реализации такой логики в PHP существует возможность переопределять родительские методы, т. е. задавать в дочерних классах методыс названиями, совпадающими в родительских классах. Реализация этих методов в родительских классах в таком случае становится неактуальной для класса-потомка. Давайте приведем пример класса NewsArticle с переопределенным методом view() :

    Class NewsArticle extends Article { $datetime; // дата публикации новости // Функция для вывода статьи function view() { echo "

    $this->title

    ". strftime("%d.%m.%y", $this->datetime). " Новость

    $this->content

    "; } }

    В приведенном коде используется функция strftime() , которая позволяет выводить даты в удобном виде. Для лучшего понимания кода ознакомьтесь со спецификацией этой функции в справочнике. Для нас же сейчас важно, чтобы вы обратили внимание на то, что класс NewsArticle , как и Article , определяет метод view() . Соответственно, все объекты этого класса будут использовать метод view() , объявленный в классе NewsArticle , а не в Article .

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

    Полиморфизм

    Полиморфизм - взаимозаменяемость объектов с одинаковым интерфейсом.

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

    Давайте рассмотрим следующий пример, который дает представление о сути полиморфизма :

    Class A { function Test() { echo "Это класс A
    "; } function Call() { $this->Test(); } } class B extends A { function Test() { echo "Это класс B
    "; } } $a = new A(); $b = new B(); $a->Call(); // выводит: "Это класс A" $b->Test(); // выводит: "Это класс B" $b->

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

    $a->Call(); // выводит: "Это класс A"

    В этой строке происходит вызов метода Call() у объекта класса А . Как и определено в функции Call() класса A , происходит вызов метода Test() . Отрабатывает метод Test() у объекта класса A , и на экран выводится текст "Это класс А ".

    $b->Test(); // выводит: "Это класс B"

    В данной строке происходит вызов метода Test() у объекта класса B . Метод Test() класса B выводит на экран текст "Это класс В ".

    $b->Call(); // выводит: "Это класс B"

    Наконец, в последней строке происходит вызов класса Call() у объекта класса В . Но в реализации класса B мы не увидим такого метода, а это значит, что он наследуется от класса A , т. к. класс B - это потомок класса A . Что же мы видим в реализации метода Call() класса A ? Следующий код:

    $this->Test();

    Метод Call() вызывает метод Test() того объекта, в котором находится. Это значит, что отработает метод Test() объекта класса B . Именно этим объясняется результат, выведенный на экране.

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

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

    Компьютер