Light-electric.com

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

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

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

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

Полиморфи́зм (от греч. πολὺ- — много, и μορφή — форма) в языках программирования — возможность объектов с одинаковой спецификацией иметь различную реализацию.

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

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

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

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

Содержание

Примеры

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

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

В объектно-ориентированных языках

В объектно-ориентированных языках класс является абстрактным типом данных. [Прим. 1] Полиморфизм реализуется с помощью наследования классов и виртуальных функций. Класс-потомок наследует сигнатуры методов класса-родителя, а реализация, в результате переопределения метода, этих методов может быть другой, соответствующей специфике класса-потомка. Другие функции могут работать с объектом как с экземпляром класса-родителя, но если при этом объект на самом деле является экземпляром класса-потомка, то во время исполнения будет вызван метод, переопределенный в классе-потомке. Это называется поздним связыванием. [Примером использования может служить обработка массива, содержащего экземпляры как класса-родителя, так и класса-потомка: очевидно, что такой массив может быть объявлен только как массив типа класса-родителя и у объектов массива могут вызываться только методы этого класса, но если в классе-потомке какие-то методы были переопределены, то в режиме исполнения для экземпляров этого класса будут вызваны именно они, а не методы класса-родителя.]

Класс-потомок сам может быть родителем. Это позволяет строить сложные схемы наследования — древовидные или сетевидные.

Абстрактные (или чисто виртуальные) методы не имеют реализации вообще (на самом деле некоторые языки, например C++, допускают реализацию абстрактных методов в родительском классе). Они специально предназначены для наследования. Их реализация должна быть определена в классах-потомках.

Класс может наследовать функциональность от нескольких классов. Это называется множественным наследованием. Множественное наследование создаёт известную проблему (в C++), когда класс наследуется от нескольких классов-посредников, которые в свою очередь наследуются от одного класса (так называемая «Проблема ромба»): если метод общего предка был переопределён в посредниках, неизвестно, какую реализацию метода должен наследовать общий потомок. Решается эта проблема путём отказа от множественного наследования для классов и разрешением множественного наследования для полностью абстрактных классов (то есть интерфейсов) (C#, Delphi, Java), либо через виртуальное наследование (C++).

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

Полиморфизм в функциональных языках будет рассмотрен на примере языка Haskell.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Читать еще:  Язык программирования c команды

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

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

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

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

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

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

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

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

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

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

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

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

Что такое полиморфизм (программирование)?

в Компьютеры 27.03.2018 0 197 Просмотров

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

Многие языки программирования поддерживают использование полиморфизма. Этот процесс позволяет повторно использовать правила и программный код во всём приложении. Не все языки программирования поддерживают полное полиморфное поведение, но большинство из них поддерживают основную концепцию. Все настоящие языки OOP, включая Java®, .net и C++®, поддерживают более продвинутые подходы и методы.

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

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

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

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

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

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

Класс (java class) описывает устройство и поведение объектов. Устройство описывается через набор характеристик (свойств), а поведение – через набор доступных для объектов операций (методов). Классы можно создавать на основе уже имеющихся, добавляя или переопределяя свойства и методы.

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

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

Наследование является неотъемлемой частью Java. При использовании наследования принимается во внимание, что новый класс, наследующий свойства базового (родительского) класса имеет все те свойства, которым обладает родитель. В коде используется операнд extends, после которого указывается имя базового класса. Тем самым открывается доступ ко всем полям и методам базового класса.

Используя наследование, можно создать общий «java class», который определяет характеристики, общие для набора связанных элементов. Затем можно наследоваться от него и создать дополнительные классы, для которых определить дополнительные уникальные для них характеристики.

Главный наследуемый класс в Java называют суперклассом super. Наследующий класс называют подклассом. Таким образом подкласс — это специализированная версия суперкласса, которая наследует все свойства суперкласса и добавляет свои собственные уникальные элементы.

Рассмотрим пример описания java class’a студента Student, который имеет имя, фамилию, возраст, и номер группы. Класс студента будем создавать на основе super класса пользователя User, у которого уже определены имя, фамилия и возраст:

Теперь создаем отдельный класс Student, наследующего свойства super класса. При наследовании класса необходимо также переопределить и конструкторы родительского класса :

Ключевое слово extends показывает, что мы наследуемся от класса User.

Ключевое слово super

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

Рассмотрим как происходит наследование с точки зрения создания объекта :

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

У суперкласса могут быть несколько перегруженных версий конструкторов, поэтому можно вызывать метод super() с разными параметрами. Программа выполнит тот конструктор, который соответствует указанным аргументам.

Читать еще:  Основы функционального программирования

Вторая форма ключевого слова super действует подобно ключевому слову this, только при этом мы всегда ссылаемся на суперкласс подкласса, в котором она использована. Общая форма имеет следующий вид:

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

В результате в консоли мы должны увидеть :

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

Если в иерархии классов имя и сигнатура типа метода подкласса совпадает с атрибутами метода суперкласса, то метод подкласса переопределяет метод суперкласса. Когда переопределённый метод вызывается из своего подкласса, он всегда будет ссылаться на версию этого метода, определённую подклассом. А версия метода из суперкласса будет скрыта.

Если нужно получить доступ к версии переопределённого метода, определённого в суперклассе, то необходимо использовать ключевое слово super.

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

В Java SE5 появилась анотация @Override;. Если необходимо переопределить метод, то используйте @Override, и компилятор выдаст сообщение об ошибке, если вместо переопределения будет случайно выполнена перегрузка.

В Java можно наследоваться только от одного класса.

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

В информатике инкапсуляцией (лат. en capsula) называется упаковка данных и/или функций в единый объект.

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

Модификаторы доступа

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

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

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

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

Пример простого описания робота

В представленном примере робота используются наборы методов, начинающие с set и get. Эту пару методов часто называют сеттер/геттер. Данные методы используются для доступа к полям объекта. Наименования метода заканчиваются наименованием поля, начинающееся с ПРОПИСНОЙ буквы.

В методах set мы передаем значение через формальный параметр во внутрь процедуры. В коде процедуры мы присваиваем значение переменной объекта/класса с использованием ключевого слова this.

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

Полиморфизм, polymorphism

Полиморфизм является одним из фундаментальных понятий в объектно-ориентированном программировании наряду с наследованием и инкапсуляцией. Слово полиморфизм греческого происхождения и означает «имеющий много форм». Чтобы понять, что означает полиморфизм применительно к объектно-ориентированному программированию, рассмотрим пример создания векторного графического редактора, в котором необходимо использовать ряд классов в виде набора графических примитивов — Square, Line, Circle, Triangle, и т.д. У каждого из этих классов необходимо определить метод draw для отображения соответствующего примитива на экране.

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

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

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

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

После этого мы создаем различные классы-наследники: Square (Квадрат), Line (Линия), Сircle (круг) и Triangle (Треугольник):

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

Теперь проверим удивительную возможность полиморфизма:

В консоль будут выведены следующие строки:

Таким образом каждый класс-наследник вызвал именно свой метод draw, вместо того, чтобы вызвать метод draw из родительского класса Shape.

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

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

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

ООП. Часть 4. Полиморфизм, перегрузка методов и операторов

C# позволяет использовать один метод для разных типов данных и даже переопределить логику операторов. Разбираемся в перегрузках.

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

В C# это реализуется с помощью перегрузок (overloading).

Евгений Кучерявый

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

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

C# — строго типизированный язык. Это значит, что вы не можете поместить строку в переменную типа int — сначала нужно провести преобразование. Так же и в метод нельзя передать параметр типа float, если при объявлении метода был указан тип double.

Однако если вы экспериментировали с методом WriteLine() класса Console, то могли заметить, что в него можно передавать аргументы разных типов:

Читать еще:  Императивные языки программирования

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

Так происходит потому, что у метода WriteLine() есть перегрузки — методы с таким же названием, но принимающие другие аргументы:

Когда вы вызовете метод Sum(), компилятор по переданным аргументам узнает, какую из его перегрузок вы имели в виду — так же, как это происходит с методом WriteLine().

При этом стоит учитывать, что значение имеют только типы и количество передаваемых аргументов. Например, можно написать такие перегрузки:

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

Оглавление

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

То же самое можно сделать и с конструкторами классов:

Альтернатива этому решению — указать значения для аргументов по умолчанию:

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

Перегрузка операторов

Перегрузить можно даже операторы, то есть:

Так как использоваться этот оператор должен без объявления экземпляра класса (item1 + item2, а не item1 item1.+ item2), то указываются модификаторы public static.

Например, мы хотим улучшать предметы в играх. Во многих MMO 1 популярна механика, когда один предмет улучшается за счёт другого. Мы можем сделать это с помощью перегрузки оператора сложения:

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

В результате в консоль будет выведено следующее:

1) MMO (англ. Massively Multiplayer Online Game, MMO, MMOG)

Массовая многопользовательская онлайн-игра

Перегрузка операторов преобразования типов

Хотя типизация в C# строгая, типы можно преобразовывать. Например, мы можем конвертировать число типа float в число типа int:

С помощью перегрузки операторов преобразования типов мы можем прописать любую логику для конвертации объектов. Для наглядности создадим класс Hero:

В этом классе хранятся данные о персонаже. В MMO часто можно увидеть такой параметр, как мощь — это сумма всех характеристик героя или предмета. Например, её можно посчитать по следующей формуле:

Мощь = (сила + ловкость + интеллект) * уровень.

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

Модификатор implicit говорит компилятору, что преобразование может быть неявным. То есть оно сработает, если написать так:

Explicit, наоборот, означает, что преобразование должно быть явным:

Вот как будет выглядеть перегрузка преобразования объекта класса Hero в int:

Вот как она будет использоваться:

Вывод в консоль будет следующим:

Проблемы читаемости

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

Или же непонятно, зачем конвертировать Hero в int. Ясность вносит название переменной (power), но этого недостаточно.

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

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

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

Домашнее задание

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

Заключение

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

Вы можете изучить ООП гораздо глубже, записавшись на курс «Профессия C#-разработчик». Он раскрывает лучшие практики работы с C# в объектно-ориентированной парадигме программирования.

Язык программирования C++

Язык С++. Полиморфизм

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

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

Чтобы использовать полиморфизм, необходимо чтобы:

1) все классы-потомки являлись наследниками одного и того же базового класса

2) функция, реализующая метод, должна быть объявлена виртуальной в базовом классе

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

Доступ к обычным методам через указатели

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

A, B, Base – это типы. Указатели на объекты производных классов совместимы по типу с указателями на объекты базового класса.

Base *ptr; ptr=&a; ptr=&b;

Однако, указатели производных классов между собой не совместимы!

Пример:

A *ptr; ptr=&a;

ptr=&b; // указатель класса A не совместим с указателем класса B.

Теперь необходимо понять, какая собственно функция выполняется в этой строчке

Это функция Base::show() или A::show() или B:show()?

Результат выполнения дает простой ответ

Base

Base

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

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

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

На выходе имеем:

Class A

Class B

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

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

Абстрактные классы и чисто виртуальные методы

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

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

Чисто виртуальная функция – это функция, после объявления которой добавлено выражение =0.

Пример: Объявить абстрактный класс person. Объявить два производных класса – student и teacher. В каждом из классов объявить метод, с помощью которого можно создать список выдающихся педагогов и студентов. Студентов со средним баллом больше 4 и педагогов с числом публикаций более 50 статей считать выдающимися.

0 0 голоса
Рейтинг статьи
Ссылка на основную публикацию
ВсеИнструменты