Что такое полиморфизм
Перейти к содержимому

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

  • автор:

Простыми словами о полиморфизме: 5‑я часть гайда по ООП

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

Иллюстрация: Катя Павловская для Skillbox Media

Максим Сафронов

Максим Сафронов

Автор, редактор, IT-журналист. Рассказывает о новых технологиях, цифровых профессиях и полезных инструментах для разработчиков. Любит играть на электрогитаре и программировать на Swift.

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

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

Все статьи про ООП
  • Что такое классы и объекты.
  • Особенности работы с объектами.
  • Модификаторы доступа, инкапсуляция.
  • Полиморфизм и перегрузка методов.
  • Полиморфизм.
  • Наследование и ещё немного полиморфизма.
  • Абстрактные классы и интерфейсы.
  • Практикум.

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

Мы уже знаем, что в ООП все программы состоят из объектов. Но у разных на вид объектов может быть одинаковый интерфейс — какие-то общие методы, которые они выполняют каждый по-своему. Например, у объектов «квадрокоптер» и «самолёт» общим методом будет «летать».

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

Грубо говоря, полиморфизм — это диспетчер в аэропорту. Ему неважно, какую топливную систему предусмотрел авиаконструктор и как работает система форсажа — он просто даёт команду: «Взлёт разрешаю». После этого на лайнере начинают происходить какие-то свои внутренние процессы, на которые диспетчер уже не влияет.

Минутка семантики. Слово «полиморфизм» переводится с греческого как «многоформенность». Смысл в том, что один и тот же метод может воплощаться по-разному — например, как полёт у дрона и самолёта.

Как полиморфизм выглядит в коде

Допустим, мы делаем онлайн-магазин с мерчем известного ютуб-канала. У нас есть три вида товаров: футболки, кружки и блокноты. Задача — сделать так, чтобы все их можно было складывать в корзину и сайт каждый раз автоматически выдавал покупателю сообщение: «Товар такой-то добавлен в корзину». Как это сделать?

Есть два варианта. Можно писать свою версию метода «добавить в корзину» на каждую категорию товара — но это долго, да и код получится неопрятный. А можно написать один полиморфный метод, а потом использовать его для каждого нового объекта — и вот это как раз наш случай. Разберём весь процесс пошагово.

Шаг 1. Создаём базовый класс «Товар»

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

public class Good // Объявляем класс «Товар» < public string name; // Указываем свойство «Название» // Создаём метод «Добавить в корзину» // Virtual означает, что метод потом можно будет дополнить под нужды конкретного товара. public virtual void AddToCart( ) < Console.WriteLine("Товар " + name + " добавлен в корзину"); > >

Пока всё это выглядит очень абстрактно, но дальше — больше.

Шаг 2. Создаём три производных класса: «Футболка», «Кружка» и «Блокнот»

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

public class Cup : Good // Создаём класс «Кружка» < public int volume; // Вводим дополнительное свойство «Объём» public override void AddToCart( ) // Override означает, что мы переопределяем метод AddToCart и добавляем ему новую функциональность < Console.WriteLine("Кружка " + name + " объёмом " + volume + " мл добавлена в корзину"); > > public class Note : Good // Создаём класс «Блокнот» < public int pages; // Добавляем свойство «Количество страниц» public override void AddToCart( ) < Console.WriteLine("Блокнот " + name + " на " + pages + " страниц добавлен в корзину"); > > public class Shirt : Good // Создаём класс «Футболка» < public int size; // Добавляем свойство «Размер» public override void AddToCart( ) < Console.WriteLine("Футболка " + name + " размером " + size + " добавлена в корзину"); > >

Шаг 3. Вызываем метод «Добавить в корзину»

Допустим, пользователь зашёл в наш магазин и решил купить три товара: футболку «Кислота» 48 размера, кружку «Омут» на 250 мл и блокнот «Древо жизни» на 180 страниц. Поставил он галочки напротив каждого товара, нажал «Добавить в корзину» — и вот какая история начинает происходить в коде:

using System; class Program < static void Main( ) < // Создаём объекты для каждого товара Shirt someShirt = new Shirt(); someShirt.name = "Кислота"; // Футболка «Кислота» someShirt.size = 48; Cup someCup = new Cup(); // Кружка «Омут» someCup.name = "Омут"; someCup.volume = 250; Note someNote = new Note(); someNote.name = "Древо жизни"; // Блокнот «Древо жизни» someNote.pages = 180; // Создаём массив из всех трёх объектов Good[] goods = new Good[3]; goods[0] = someShirt; goods[1] = someCup; goods[2] = someNote // С помощью цикла вызываем метод «Добавить в корзину» для каждого товара for(int i = 0; i < 3; i++) < goods[i].AddToCart(); >> >

Мы объединили товары в массив и с помощью цикла применили метод AddToCart сразу ко всем. Если бы наш магазин был реальным, пользователь получил бы примерно такие сообщения:

Футболка «Кислота размером» 48 добавлена в корзину Кружка «Омут» объёмом 250 мл добавлена в корзину Блокнот «Древо жизни» на 180 страниц добавлен в корзину

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

Для чего нужен полиморфизм

Смысл полиморфизма в том, что нам не надо писать для каждого товара свой метод — например, какой-нибудь AddToCartShirt для футболки или AddToCartCup для кружки. У нас просто есть один AddToCart, и мы на него полагаемся. Если в магазине появятся, например, кепки, мы просто немного допилим наш метод под особенности кепок, и дело в шляпе.

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

Отсюда можно выделить три главных преимущества полиморфизма:

  • Читаемость. Чем меньше кода и чем лучше он упакован, тем проще работать программистам и тем быстрее идёт разработка.
  • Масштабируемость. Можно добавить в магазин носки, ручки, напульсники, подвески и ещё кучу разных товаров, а за их покупку всё равно будет отвечать одна команда — AddToCart.
  • Предсказуемость кода. Когда у нас есть один метод для разных объектов, мы чувствуем себя спокойно. Можно не переживать, что команда «Добавить в корзину трусы» случайно применится к носкам и вызовет какой-то сбой в программе.

Что дальше

В ООП под полиморфизмом понимают только одну его разновидность — полиморфизм подтипов. Он как раз отвечает за то, чтобы объекты разных классов можно было вызывать одним методом. Но существует ещё два вида полиморфизма: параметрический и ad-hoc. О них мы и поговорим в следующих статьях — разберёмся, чем они различаются и для чего нужны.

Читайте также:

  • Что такое объекты и классы: 1-я часть гайда по ООП
  • Тест: что ты знаешь о создателе Python Гвидо ван Россуме?
  • Как изучить Python самостоятельно и бесплатно

Полиморфизм

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

С греческого языка слово «полиморфизм» означает «многообразие». Термин используют и в других сферах. Скажем, полиморфизм в биологии — способность какого-то вида существовать в разных формах.

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

Освойте профессию
«Fullstack-разработчик на Python»

Профессия / 12 месяцев
Fullstack-разработчик на Python

Создавайте веб-проекты самостоятельно

dffsdd (3)

Fullstack-разработчик на Python

Fullstack-разработчики могут в одиночку сделать IT-проект от архитектуры до интерфейса. Их навыки востребованы у работодателей, особенно в стартапах. Научитесь программировать на Python и JavaScript и создавайте сервисы с нуля.

картинка - 2023-03-14T190323.524

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

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

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

Для чего нужен полиморфизм

  • Облегчает написание кода. Не нужно придумывать десять разных методов: отправить одно, другое, третье. Есть один метод, который можно применять к разным сущностям и не задумываться.
  • Позволяет масштабировать решения. Если понадобится отправлять не только видео и картинки, но и текст, это можно будет сделать той же командой.
  • Делает код более читаемым. Разработчику не нужно разбираться, что делает десяток методов с похожими названиями. Есть один метод, и по его названию все понятно.
  • Помогает точно понимать, чего ждать от разных методов, то есть делает код более предсказуемым. Не может быть такого, что метод «Отправить» вдруг окажется методом не для картинки, а для видео.

С понятием должен быть знаком любой разработчик. Множество языков программирования используют полиморфизм: C, C++, Java, Python и другие. Не все эти языки чисто объектно-ориентированные: некоторые устроены так, что с ними можно работать в разных парадигмах программирования. Так что столкнуться с полиморфизмом может каждый.

Станьте Fullstack-разработчик на Python и найдите стабильную работу
на удаленке

Полиморфизм как принцип ООП

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

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

Абстракция — это принцип, когда какие-то общие вещи сводятся до набора абстрактных признаков. То есть мы имеем не абсолютно разные классы «картинка», «видео», «текст», а абстрактный класс «контент».

Наследование — это возможность делать на основе одних сущностей другие. Обычно в качестве «родителя» используются абстрактные сущности, а от них наследуются уже более конкретные. То есть если родитель — «контент», то дети — «картинка», «видео», «текст». Это все подвиды контента и его наследники.

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

Что такое полиморфный метод и как его создают

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

Сначала программист создает общий класс. Например, «контент». В нем он описывает вещи, общие для всего контента: свойства и методы. Свойства — это признаки, то, что есть у контента: количество лайков, возможность комментирования и так далее. А методы — это действия, то есть команды: контент можно лайкнуть, открыть на отдельной вкладке, репостнуть или отправить в личное сообщение.

У общего класса — абстрактные, общие методы. Контент можно отправить, но как — пока непонятно. Зато уже можно описать, как будет выглядеть эта команда: как она называется, что в нее нужно передать, какое сообщение выдать после этого. Это своего рода каркас будущего конкретного действия.

Затем разработчик создает производные классы. Это наследники общего класса: они более конкретные, у них могут быть дополнительные свойства и методы. Например, видео можно поставить на паузу, а картинку — нет. А еще у них сохраняются абстрактные свойства и методы родителя: их переопределяют, чтобы они тоже работали конкретнее.

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

Можно создавать объекты производных классов и пользоваться их методами. Абстрактные классы существуют как бы в вакууме: нельзя создать объект, который будет принадлежать такому классу. Среди реальных объектов не может быть «просто контента», который не является ни текстом, ни картинкой, ни видео, ни еще чем-то. Соответственно, абстрактные методы никто не будет вызывать. А вот переопределенные методы из производных классов — вполне реальные, ими можно пользоваться в разных ситуациях.

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

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

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

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

Полиморфизм ad hoc. Этот вид полиморфизма еще называют специализированным. Его иногда противопоставляют параметрическому: идея ad hoc — разный код при одинаковом названии. Часто такой полиморфизм реализуют с помощью перегрузки методов: несколько раз пишут метод с одним и тем же названием, но разным кодом.

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

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

  • Статический — метод переопределяют при компиляции.
  • Динамический — при выполнении программы.

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

Преимущества полиморфизма

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

Недостатки полиморфизма

  • Связь полиморфизма с наследованием порой расценивают как слабое место всей концепции. Если нужен полиформный класс, но для конкретной ситуации не подходит наследование, — реализация может усложниться.
  • Не всегда полиморфизм легко реализовать на практике. Поэтому существует довольно много реализаций, которые работают плохо: с багами и необъяснимыми ошибками.
  • Полиморфизм может ухудшать производительность кода, делать его более «тяжелым» и медленным. Но тут многое зависит от реализации: скажем, параметрический обычно быстрее, чем ad hoc.
  • Новичкам бывает тяжело понять принцип — объяснить полиморфизм простыми словами можно только в связке с другими понятиями ООП. Так что человек на момент изучения уже должен понимать, что такое объектно-ориентированное программирование.

Как начать изучать полиморфизм

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

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

Полиморфизм

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

Например, два разных класса содержат метод total , однако инструкции каждого предусматривают совершенно разные операции. Так в примере ниже в классе T1 – это прибавление 10 к аргументу, в T2 – подсчет длины строки символов. В зависимости от того, к объекту какого класса применяется метод total , выполняются те или иные инструкции.

class T1: def __init__(self): self.n = 10 def total(self, a): return self.n + int(a) class T2: def __init__(self): self.string = 'Hi' def total(self, a): return len(self.string + str(a)) t1 = T1() t2 = T2() print(t1.total(35)) # Вывод: 45 print(t2.total(35)) # Вывод: 4

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

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

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

В Python среди прочего полиморфизм находит отражение в методах перегрузки операторов. Два из них мы уже рассмотрели. Это __init__ и __del__ , которые вызываются при создании объекта и его удалении. Полиморфизм у методов перегрузки операторов проявляется в том, что независимо от типа объекта, его участие в определенной операции, вызывает метод с конкретным именем. В случае __init__ операцией является создание объекта.

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

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

class A: def __init__(self, v1, v2): self.field1 = v1 self.field2 = v2 a = A(3, 4) b = str(a) print(a) print(b)

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

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

class A: def __init__(self, v1, v2): self.field1 = v1 self.field2 = v2 def __str__(self): s = str(self.field1)+" "+str(self.field2) return s a = A(3, 4) b = str(a) print(a) print(b)
3 4 3 4

Какую именно строку возвращает метод __str__() , дело десятое. Он вполне может строить квадратик из символов:

class Rectangle: def __init__(self, width, height, sign): self.w = int(width) self.h = int(height) self.s = str(sign) def __str__(self): rect = [] # количество строк for i in range(self.h): # знак повторяется w раз rect.append(self.s * self.w) # превращаем список в строку rect = '\n'.join(rect) return rect b = Rectangle(10, 3, '*') print(b)

Практическая работа. Метод перегрузки оператора сложения

В качестве практической работы попробуйте самостоятельно перегрузить оператор сложения. Для его перегрузки используется метод __add__ . Он вызывается, когда объекты класса, имеющего данный метод, фигурируют в операции сложения, причем с левой стороны. Это значит, что в выражении a + b у объекта a должен быть метод __add__ . Объект b может быть чем угодно, но чаще всего он бывает объектом того же класса. Объект b будет автоматически передаваться в метод __add__(self, b) в качестве второго аргумента.

Отметим, в Python также есть правосторонний метод перегрузки сложения – __radd__ .

Согласно полиморфизму ООП, возвращать метод __add__ может что угодно. Может вообще ничего не возвращать, а «молча» вносить изменения в какие-то уже существующие объекты. Допустим, в вашей программе метод перегрузки сложения будет возвращать новый объект того же класса.

Курс с примерами решений практических работ:
pdf-версия

X Скрыть Наверх

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

Полиморфизм для начинающих

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

Постановка задачи

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

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

Абстрактный класс

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

abstract class Publication
// таблица, в которой хранятся данные по элементу
protected $table ;

// свойства элемента нам неизвестны
protected $properties = array();

// конструктор
public function __construct ( $id )
// обратите внимание, мы не знаем, из какой таблицы нам нужно получить данные
$result = mysql_query ( ‘SELECT * FROM `’ . $this -> table . ‘` WHERE `id` #007700″>. $id . ‘» LIMIT 1’ );
// какие мы получили данные, мы тоже не знаем
$this -> properties = mysql_fetch_assoc ( $result );
>

// метод, одинаковый для любого типа публикаций, возвращает значение свойства
public function get_property ( $name )
if (isset( $this -> properties [ $name ]))
return $this -> properties [ $name ];

// метод, одинаковый для любого типа публикаций, устанавливает значение свойства
public function set_property ( $name , $value )
if (!isset( $this -> properties [ $name ]))
return false ;

$this -> properties [ $name ] = $value ;

// а этот метод должен напечатать публикацию, но мы не знаем, как именно это сделать, и потому объявляем его абстрактным
abstract public function do_print ();
>

Производные классы

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

class News extends Publication
// конструктор класса новостей, производного от класса публикаций
public function __construct ( $id )
// устанавливаем значение таблицы, в которой хранятся данные по новостям
$this -> table = ‘news_table’ ;
// вызываем конструктор родительского класса
parent :: __construct ( $id );
>

// переопределяем абстрактный метод печати
public function do_print ()
echo $this -> properties [ ‘title’ ];
echo ‘

‘ ;
echo $this -> properties [ ‘text’ ];
echo ‘
Источник: ‘ . $this -> properties [ ‘source’ ];
>
>

class Announcement extends Publication
// конструктор класса объявлений, производного от класса публикаций
public function __construct ( $id )
// устанавливаем значение таблицы, в которой хранятся данные по объявлениям
$this -> table = ‘announcements_table’ ;
// вызываем конструктор родительского класса
parent :: __construct ( $id );
>

// переопределяем абстрактный метод печати
public function do_print ()
echo $this -> properties [ ‘title’ ];
echo ‘
Внимание! Объявление действительно до ‘ . $this -> properties [ ‘end_date’ ];
echo ‘

‘ . $this -> properties [ ‘text’ ];
>
>

class Article extends Publication
// конструктор класса статей, производного от класса публикаций
public function __construct ( $id )
// устанавливаем значение таблицы, в которой хранятся данные по статьям
$this -> table = ‘articles_table’ ;
// вызываем конструктор родительского класса
parent :: __construct ( $id );
>

// переопределяем абстрактный метод печати
public function do_print ()
echo $this -> properties [ ‘title’ ];
echo ‘

‘ ;
echo $this -> properties [ ‘text’ ];
echo ‘
© ‘ . $this -> properties [ ‘author’ ];
>
>

Теперь об использовании

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

// наполняем массив публикаций объектами, производными от Publication
$publications [] = new News ( $news_id );
$publications [] = new Announcement ( $announcement_id );
$publications [] = new Article ( $article_id );

foreach ( $publications as $publication ) // если мы работаем с наследниками Publication
if ( $publication instanceof Publication ) // то печатаем данные
$publication -> do_print ();
> else // исключение или обработка ошибки
>
>

Вот и все. Легким движением руки брюки превращаются в элегантные шорты :-).

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

Немного теории

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

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *