Что такое полиморфизм, для чего он нужен и как он используется?
Я смотрел видео Google Tech Talks, и они часто ссылались на полиморфизм.
Что такое полиморфизм, для чего он нужен и как он используется?
29 ответов
Если вы думаете о греческих корнях термина, это должно стать очевидным.
- Поли = много: многоугольник = многогранно, полистирол = много стиролов (а), полиглот = много языков и так далее.
- Морф = изменение или форма: морфология = изучение биологической формы, Морфеус = греческий бог снов, способный принимать любую форму.
Таким образом, полиморфизм - это способность (в программировании) представлять один и тот же интерфейс для различных базовых форм (типов данных).
Например, во многих языках целые числа и числа с плавающей запятой неявно полиморфны, так как вы можете добавлять, вычитать, умножать и так далее, независимо от того, что типы разные. Они редко рассматриваются как объекты в обычном выражении.
Но так же, как класс BigDecimal
или же Rational
или же Imaginary
может также предоставлять эти операции, даже если они работают с различными типами данных.
Классическим примером является Shape
класс и все классы, которые могут наследовать от него (квадрат, круг, додекаэдр, неправильный многоугольник, сплат и т. д.).
При полиморфизме каждый из этих классов будет иметь разные базовые данные. Точечной форме нужны только две координаты (конечно, при условии, что она находится в двумерном пространстве). Круг нуждается в центре и радиусе. Квадрат или прямоугольник требуют двух координат для верхнего левого и нижнего правого углов и (возможно) вращения. Нерегулярный многоугольник нуждается в серии линий.
Делая класс ответственным за его код, а также за свои данные, вы можете достичь полиморфизма. В этом примере у каждого класса будет свой Draw()
Функция и код клиента могут просто сделать:
shape.Draw()
чтобы получить правильное поведение для любой формы.
Это в отличие от старого способа делать вещи, в которых код был отделен от данных, и у вас были бы такие функции, как drawSquare()
а также drawCircle()
,
Ориентация на объект, полиморфизм и наследование - все тесно связанные понятия, и их важно знать. За мою долгую карьеру было много "серебряных пуль", которые в основном просто сошли на нет, но парадигма ОО оказалась хорошей. Изучите это, поймите это, любите это - Вы будете рады, что сделали:-)
(а) Я первоначально написал это как шутку, но она оказалась правильной и, следовательно, не такой уж смешной. Мономер стирола, случается, сделан из углерода и водорода, C8H8
и полистирол сделан из групп этого, (C8H8)n
,
Возможно, я должен был заявить, что полип был много случаев в письме p
хотя теперь, когда мне пришлось объяснить шутку, даже это не кажется смешным.
Иногда вы должны просто выйти, пока вы позади:-)
Полиморфизм - это когда вы можете рассматривать объект как универсальную версию чего-либо, но когда вы получаете к нему доступ, код определяет, какой именно это тип, и вызывает соответствующий код.
Вот пример в C#. Создайте четыре класса в консольном приложении:
public abstract class Vehicle
{
public abstract int Wheels;
}
public class Bicycle : Vehicle
{
public override int Wheels()
{
return 2;
}
}
public class Car : Vehicle
{
public override int Wheels()
{
return 4;
}
}
public class Truck : Vehicle
{
public override int Wheels()
{
return 18;
}
}
Теперь создайте следующее в Main() модуля для консольного приложения:
public void Main()
{
List<Vehicle> vehicles = new List<Vehicle>();
vehicles.Add(new Bicycle());
vehicles.Add(new Car());
vehicles.Add(new Truck());
foreach (Vehicle v in vehicles)
{
Console.WriteLine(
string.Format("A {0} has {1} wheels.",
v.GetType().Name, v.Wheels));
}
}
В этом примере мы создаем список базового класса Vehicle, который не знает, сколько колес имеет каждый из его подклассов, но знает, что каждый подкласс отвечает за знание того, сколько у него колес.
Затем мы добавляем в список велосипед, автомобиль и грузовик.
Затем мы можем циклически проходить по каждому Транспортному средству в списке и обрабатывать их все одинаково, однако, когда мы получаем доступ к свойству каждого Транспортного средства "Колеса", класс Vehicle передает выполнение этого кода соответствующему подклассу.
Этот код называется полиморфным, так как точный код, который выполняется, определяется подклассом, на который ссылаются во время выполнения.
Я надеюсь, что это поможет вам.
От понимания и применения полиморфизма в PHP, спасибо Steve Guidetti.
Полиморфизм - это длинное слово для очень простого понятия.
Полиморфизм описывает шаблон в объектно-ориентированном программировании, в котором классы имеют различную функциональность при совместном использовании общего интерфейса.
Прелесть полиморфизма в том, что коду, работающему с разными классами, не нужно знать, какой класс он использует, поскольку все они используются одинаково. Реальная аналогия полиморфизма - это кнопка. Все знают, как использовать кнопку: вы просто нажимаете на нее. Однако то, что "делает" кнопка, зависит от того, с чем она связана, и от контекста, в котором она используется, но результат не влияет на то, как она используется. Если ваш босс говорит вам нажать кнопку, у вас уже есть вся информация, необходимая для выполнения задачи.
В мире программирования полиморфизм используется, чтобы сделать приложения более модульными и расширяемыми. Вместо беспорядочных условных выражений, описывающих различные варианты действий, вы создаете взаимозаменяемые объекты, которые выбираете в зависимости от ваших потребностей. Это основная цель полиморфизма.
Если кто-нибудь говорит, что CUT этим людям
- Хирург
- Стилист
- Актер
Что случится?
- Хирург начнет делать надрез.
- Стилист начал бы подстригать чьи-то волосы.
- Актер внезапно прекратил бы действовать вне текущей сцены, ожидая режиссерского руководства.
Таким образом, приведенное выше представление показывает, что такое полиморфизм (то же имя, другое поведение) в ООП.
Если вы идете на собеседование, и интервьюер попросит вас рассказать / показать пример из жизни в полимере в той же комнате, где мы сидим, скажем:
Ответ - Дверь / Окна
Хотите знать, как?
Через дверь / окно - может прийти человек, может прийти воздух, может прийти свет, может прийти дождь и т. Д.
Чтобы понять это лучше и проще, я использовал приведенный выше пример. Если вам нужна ссылка на код, следуйте приведенным выше ответам.
Простое объяснение по аналогии
Президент США использует полиморфизм. Как? Ну, у него много советников:
- Военные советники
- Юрисконсульты
- Ядерные физики (в качестве советников)
- Медицинские консультанты
- и т. д.
Каждый должен отвечать только за одно: Пример:
Президент не является экспертом ни по цинкованию, ни по квантовой физике. Он не знает многих вещей - но он знает только одно: как управлять страной.
То же самое с кодом: проблемы и обязанности должны быть разделены между соответствующими классами / людьми. В противном случае у вас был бы президент, знающий буквально все в мире - всю Википедию. Представьте себе, что в вашем коде есть вся википедия: это было бы ужасно.
Почему это плохая идея для президента знать все эти конкретные вещи?
Если бы президент специально говорил людям, что делать, это означало бы, что президент должен точно знать, что делать. Если президенту нужно знать конкретные вещи самому, это означает, что когда вам нужно внести изменения, вам нужно сделать это в двух местах, а не в одном.
Например, если EPA изменит законы о загрязнении, то когда это произойдет: вам нужно будет изменить класс EPA, а также класс президента. Изменение кода в двух местах, а не в одном, может быть опасным, потому что его гораздо сложнее поддерживать.
Есть ли лучший подход?
Есть лучший подход: президенту не нужно знать специфику чего-либо - он может требовать лучшего совета от людей, которым конкретно поручено делать эти вещи.
Он может использовать полиморфный подход к управлению страной.
Пример - использования полиморфного подхода:
Все, что президент делает, это просит людей посоветовать ему - и это то, что он на самом деле делает в реальной жизни - и это то, что должен делать хороший президент. все его советники реагируют по-разному, но все они знают, что президент имеет в виду: Advise(). У него сотни людей, стекающихся в его офис. На самом деле не имеет значения, кто они. Все, что президент знает, это то, что, когда он просит их "посоветовать", они знают, как реагировать соответственно:
public class MisterPresident
{
public void RunTheCountry()
{
// assume the Petraeus and Condi classes etc are instantiated.
Petraeus.Advise(); // # Petraeus says send 100,000 troops to Fallujah
Condolezza.Advise(); // # she says negotiate trade deal with Iran
HealthOfficials.Advise(); // # they say we need to spend $50 billion on ObamaCare
}
}
Такой подход позволяет президенту управлять страной буквально, не зная ничего о военной технике, здравоохранении или международной дипломатии: детали оставлены на усмотрение экспертов. Единственное, что нужно знать президенту, это: "Advise()".
Что вы не хотите:
public class MisterPresident
{
public void RunTheCountry()
{
// people walk into the Presidents office and he tells them what to do
// depending on who they are.
// Fallujah Advice - Mr Prez tells his military exactly what to do.
petraeus.IncreaseTroopNumbers();
petraeus.ImproveSecurity();
petraeus.PayContractors();
// Condi diplomacy advice - Prez tells Condi how to negotiate
condi.StallNegotiations();
condi.LowBallFigure();
condi.FireDemocraticallyElectedIraqiLeaderBecauseIDontLikeHim();
// Health care
healthOfficial.IncreasePremiums();
healthOfficial.AddPreexistingConditions();
}
}
НЕТ! НЕТ! НЕТ! В вышеупомянутом сценарии президент делает всю работу: он знает об увеличении численности войск и уже существующих условиях. Это означает, что если ближневосточная политика изменится, то президент должен будет изменить свои команды, а также класс Петреуса. Нам нужно только изменить класс Петреуса, потому что президенту не нужно увязать в таких деталях. Ему не нужно знать о деталях. Все, что ему нужно знать, это то, что, если он сделает один заказ, обо всем позаботятся. Все детали должны быть оставлены на усмотрение экспертов.
Это позволяет президенту делать то, что он делает лучше всего: устанавливать общую политику, хорошо выглядеть и играть в гольф:P.
Как это на самом деле реализовано - через базовый класс или общий интерфейс
По сути это полиморфизм, в двух словах. Как именно это сделано? Посредством "реализации общего интерфейса" или использования базового класса (наследования) - см. Ответы выше, которые более подробно описывают это. (Чтобы лучше понять эту концепцию, вам нужно знать, что такое интерфейс, и вам нужно будет понять, что такое наследование. Без этого вы можете бороться.)
Другими словами, Petraeus, Condi и HealthOfficials будут классами, которые "реализуют интерфейс" - назовем это IAdvisor
интерфейс, который содержит только один метод: Advise()
, Но теперь мы углубляемся в специфику.
Это было бы идеально
public class MisterPresident
{
// You can pass in any advisor: Condi, HealthOfficials, Petraeus etc. The president has no idea who it will be. But he does know that he can ask them to "advise" and that's all Mr Prez cares for.
public void RunTheCountry(IAdvisor governmentOfficer)
{
governmentOfficer.Advise();
}
}
public class USA
{
MisterPresident president;
public USA(MisterPresident president)
{
this.president = president;
}
public void ImplementPolicy()
{
IAdvisor governmentOfficer = getAdvisor(); // Returns an advisor: could be condi, or petraus etc.
president.RunTheCountry(governmentOfficer);
}
}
Резюме
Все, что вам действительно нужно знать, это:
- Президенту не нужно знать специфику - это оставлено другим.
- Все, что нужно знать президенту, это спрашивать, кто когда-либо входит в дверь, чтобы дать ему совет - и мы знаем, что они будут абсолютно точно знать, что делать, когда их попросят дать совет (потому что все они на самом деле, советники (или IAdvisors:))
Я действительно надеюсь, что это поможет вам. Если вы ничего не понимаете, оставьте комментарий, и я попробую еще раз.
Полиморфизм - это способность обрабатывать класс объекта как родительский класс.
Например, предположим, что есть класс с именем Animal и класс с именем Dog, который наследуется от Animal. Полиморфизм - это способность рассматривать любой объект Dog как объект Animal следующим образом:
Dog* dog = new Dog;
Animal* animal = dog;
Полиморфизм:
Это концепция объектно-ориентированного программирования. Способность разных объектов реагировать, каждый по-своему, на идентичные сообщения называется полиморфизмом.
Полиморфизм является результатом того, что каждый класс живет в своем собственном пространстве имен. Имена, назначенные в определении класса, не конфликтуют с именами, присвоенными где-либо за его пределами. Это верно как для переменных экземпляра в структуре данных объекта, так и для методов объекта:
Как поля структуры C находятся в защищенном пространстве имен, так и переменные экземпляра объекта.
Имена методов также защищены. В отличие от имен функций C, имена методов не являются глобальными символами. Имя метода в одном классе не может конфликтовать с именами методов в других классах; два очень разных класса могут реализовывать методы с одинаковыми именами.
Имена методов являются частью интерфейса объекта. Когда отправляется сообщение, запрашивающее, чтобы объект что-то сделал, в сообщении указывается метод, который должен выполнить объект. Поскольку разные объекты могут иметь методы с одинаковыми именами, значение сообщения необходимо понимать относительно конкретного объекта, который получает сообщение. Одно и то же сообщение, отправленное двум разным объектам, может вызывать два разных метода.
Основным преимуществом полиморфизма является то, что он упрощает интерфейс программирования. Это позволяет устанавливать соглашения, которые могут быть повторно использованы в классе после класса. Вместо того, чтобы придумывать новое имя для каждой новой функции, которую вы добавляете в программу, одни и те же имена можно использовать повторно. Интерфейс программирования можно описать как набор абстрактных поведений, совершенно отдельно от классов, которые их реализуют.
Примеры:
Пример 1: Вот простой пример, написанный на Python 2.x.
class Animal:
def __init__(self, name): # Constructor of the class
self.name = name
def talk(self): # Abstract method, defined by convention only
raise NotImplementedError("Subclass must implement abstract method")
class Cat(Animal):
def talk(self):
return 'Meow!'
class Dog(Animal):
def talk(self):
return 'Woof! Woof!'
animals = [Cat('Missy'),
Dog('Lassie')]
for animal in animals:
print animal.name + ': ' + animal.talk()
Пример 2: Полиморфизм реализован в Java с использованием перегрузки методов и концепций переопределения методов.
Рассмотрим пример автомобиля для обсуждения полиморфизма. Возьмите любой бренд, как Форд, Хонда, Тойота, БМВ, Бенц и т.д.
Но у каждого есть свои собственные расширенные функции и более продвинутые технологии, связанные с их поведением при перемещении.
Теперь давайте создадим базовый тип автомобиля
Car.java
public class Car {
int price;
String name;
String color;
public void move(){
System.out.println("Basic Car move");
}
}
Давайте реализуем пример Ford Car.
Ford расширяет тип Car, чтобы наследовать всех его членов (свойства и методы).
Ford.java
public class Ford extends Car{
public void move(){
System.out.println("Moving with V engine");
}
}
Приведенный выше класс Ford расширяет класс Car, а также реализует метод move(). Несмотря на то, что метод перемещения уже доступен для Ford через Наследование, Ford все же реализовал этот метод по-своему. Это называется переопределением метода.
Honda.java
public class Honda extends Car{
public void move(){
System.out.println("Move with i-VTEC engine");
}
}
Как и Ford, Honda также расширяет тип автомобилей и по-своему реализует метод перемещения.
Переопределение метода является важной особенностью для включения полиморфизма. Используя переопределение метода, подтипы могут изменить способ работы методов, доступных через наследование.
PolymorphismExample.java
public class PolymorphismExample {
public static void main(String[] args) {
Car car = new Car();
Car f = new Ford();
Car h = new Honda();
car.move();
f.move();
h.move();
}
}
Пример вывода полиморфизма:
В основном методе класса PolymorphismExample я создал три объекта - автомобиль, Ford и Honda. Все три объекта относятся к типу автомобиля.
Обратите внимание на важный момент: тип суперкласса может ссылаться на тип объекта подкласса, но обратный вариант невозможен. Причина в том, что все члены суперкласса доступны для подкласса с использованием наследования, и во время компиляции компилятор пытается оценить, имеет ли используемый нами ссылочный тип метод, к которому он пытается обратиться.
Так, для ссылок car, f и h в PolymorphismExample, метод move существует из типа Car. Таким образом, компилятор проходит процесс компиляции без каких-либо проблем.
Но когда дело доходит до выполнения во время выполнения, виртуальная машина вызывает методы для объектов, которые являются подтипами. Таким образом, метод move() вызывается из их соответствующих реализаций.
Таким образом, все объекты относятся к типу Car, но во время выполнения выполнение зависит от объекта, для которого происходит вызов. Это называется полиморфизмом.
Обычно это относится к способности объекта типа A вести себя как объект типа B. В объектно-ориентированном программировании это обычно достигается наследованием. Некоторые ссылки на Википедию, чтобы узнать больше:
РЕДАКТИРОВАТЬ: исправлены неработающие ссылки.
Полиморфизм такой:
class Cup {
int capacity
}
class TeaCup : Cup {
string flavour
}
class CoffeeCup : Cup {
string brand
}
Cup c = new CoffeeCup();
public int measure(Cup c) {
return c.capacity
}
Вы можете передать только Кубок вместо конкретного экземпляра. Это помогает в общем, потому что вам не нужно предоставлять конкретный экземпляр measure() для каждого типа чашки
Я знаю, что это старый вопрос с множеством хороших ответов, но я хотел бы включить один ответ:
Обрабатывать производный тип, как если бы это был его базовый тип.
Выше приведено множество примеров, демонстрирующих это в действии, но я считаю, что это хороший лаконичный ответ.
(Я просматривал другую статью о чем-то совершенно ином... и всплыл полиморфизм... Теперь я подумал, что знаю, что такое полиморфизм... но, видимо, не так красиво объяснил... Хотел написать где-нибудь... лучше еще поделюсь...)
http://www.eioba.com/a/1htn/how-i-explained-rest-to-my-wife
читать дальше из этой части:
..... полиморфизм. Это отвратительный способ сказать, что к разным существительным может применяться один и тот же глагол.
Вообще говоря, это возможность взаимодействовать с несколькими различными типами объектов, используя один и тот же или внешне похожий API. Существуют различные формы:
Перегрузка функций: определение нескольких функций с одинаковыми именами и разными типами параметров, такими как sqrt(float), sqrt(double) и sqrt(complex). В большинстве языков, которые позволяют это, компилятор автоматически выбирает правильный тип передаваемого в него аргумента, таким образом, это полиморфизм во время компиляции.
Виртуальные методы в ООП: метод класса может иметь различные реализации, адаптированные к специфике его подклассов; говорят, что каждый из них переопределяет реализацию, заданную в базовом классе. Учитывая объект, который может иметь базовый класс или любой из его подклассов, правильная реализация выбирается на лету, таким образом, это полиморфизм во время выполнения.
Шаблоны: функция некоторых ОО-языков, посредством которой функция, класс и т. Д. Могут параметризоваться по типу. Например, вы можете определить общий шаблонный класс "list", а затем создать его экземпляр как "список целых чисел", "список строк", возможно, даже "список списков строк" или тому подобное. Обычно вы пишете код один раз для структуры данных произвольного типа элемента, и компилятор генерирует его версии для различных типов элементов.
В объектно-ориентированном программировании полиморфизм относится к способности языка программирования обрабатывать объекты по-разному в зависимости от их типа данных или класса. Более конкретно, это возможность переопределять методы для производных классов.
Термин полиморфизм происходит от:
поли = много
морфизм = способность меняться
В программировании полиморфизм - это "техника", которая позволяет вам "смотреть" на объект как на предмет более чем одного типа. Например:
Объект студента также является объектом личности. Если вы "посмотрите" (то есть на актера) на студента, вы, вероятно, можете попросить студенческий билет. Вы не можете всегда делать это с человеком, верно? (человек не обязательно является студентом, поэтому может не иметь студенческого билета). Однако у человека, вероятно, есть имя. Студент тоже.
В итоге, "взгляд" на один и тот же объект с разных "углов" может дать вам разные "перспективы" (то есть разные свойства или методы)
Таким образом, эта техника позволяет создавать вещи, на которые можно "смотреть" с разных сторон.
Почему мы используем полиморфизм? Для начала... абстракция. На данный момент должно быть достаточно информации:)
Я предоставил общий обзор полиморфизма для другого вопроса:
Надеюсь, поможет. Выписка...
... это помогает начать с простого теста и определения [полиморфизма]. Рассмотрим код:
Type1 x;
Type2 y;
f(x);
f(y);
Вот,
f()
должен выполнить некоторую операцию и получает значенияx
а такжеy
в качестве входных данных. Быть полиморфным,f()
должен уметь работать со значениями как минимум двух разных типов (например,int
а такжеdouble
), поиск и выполнение кода, соответствующего типу.
(продолжение в Полиморфизме в C++)
Полиморфизм - это способность объекта, которую можно принимать во многих формах. Например, в человеческом классе человек может действовать во многих формах, когда мы говорим об отношениях. Пример: мужчина является отцом своего сына, он муж своей жены и учитель своих учеников.
Давайте использовать аналогию. Для данного музыкального сценария каждый музыкант, который играет его, дает свое собственное прикосновение в интерпретации.
Музыкант может быть абстрагирован от интерфейсов, жанр, к которому принадлежит музыкант, может быть абстрактным классом, который определяет некоторые глобальные правила интерпретации, и каждый музыкант, который играет, может быть смоделирован с конкретным классом.
Если вы слушаете музыкальное произведение, у вас есть ссылка на сценарий, например, "Фуга и Токата" Баха, и каждый музыкант, исполняющий его, делает это полиморфным по-своему.
Это всего лишь пример возможного дизайна (на Java):
public interface Musician {
public void play(Work work);
}
public interface Work {
public String getScript();
}
public class FugaAndToccata implements Work {
public String getScript() {
return Bach.getFugaAndToccataScript();
}
}
public class AnnHalloway implements Musician {
public void play(Work work) {
// plays in her own style, strict, disciplined
String script = work.getScript()
}
}
public class VictorBorga implements Musician {
public void play(Work work) {
// goofing while playing with superb style
String script = work.getScript()
}
}
public class Listener {
public void main(String[] args) {
Musician musician;
if (args!=null && args.length > 0 && args[0].equals("C")) {
musician = new AnnHalloway();
} else {
musician = new TerryGilliam();
}
musician.play(new FugaAndToccata());
}
Полиморфизм - это способность объекта принимать различные формы. Наиболее распространенное использование полиморфизма в ООП происходит, когда ссылка на родительский класс используется для ссылки на объект дочернего класса. В этом примере, написанном на Java, у нас есть три типа транспортных средств. Мы создаем три разных объекта и пытаемся запустить их колеса методом:
public class PolymorphismExample {
public static abstract class Vehicle
{
public int wheels(){
return 0;
}
}
public static class Bike extends Vehicle
{
@Override
public int wheels()
{
return 2;
}
}
public static class Car extends Vehicle
{
@Override
public int wheels()
{
return 4;
}
}
public static class Truck extends Vehicle
{
@Override
public int wheels()
{
return 18;
}
}
public static void main(String[] args)
{
Vehicle bike = new Bike();
Vehicle car = new Car();
Vehicle truck = new Truck();
System.out.println("Bike has "+bike.wheels()+" wheels");
System.out.println("Car has "+car.wheels()+" wheels");
System.out.println("Truck has "+truck.wheels()+" wheels");
}
}
Результат:
Для получения дополнительной информации, пожалуйста, посетите https://github.com/m-vahidalizadeh/java_advanced/blob/master/src/files/PolymorphismExample.java. Я надеюсь, что это помогает.
Полиморфизм в ООП означает, что класс может иметь разные типы, наследование является одним из способов реализации полиморфизма.
например, Shape - это интерфейс, он имеет подтипы Square, Circle, Diamond. теперь у вас есть объект Square, вы можете автоматически переместить квадрат в форму, потому что квадрат - это форма. Но когда вы пытаетесь уменьшить Shape to Square, вы должны выполнять явное приведение типов, потому что вы не можете сказать, что Shape is Square, это может быть и Circle. так что вам нужно вручную привести его с кодом, как Square s = (Square)shape
что если форма круг, вы получите java.lang.ClassCastException
потому что круг не квадратный
Полиморфизм => Различное исполнение в соответствии с экземпляром класса, а не типом ссылочной переменной.
Ссылочная переменная типа интерфейса может ссылаться на любой экземпляр класса, который реализует этот интерфейс.
Полиморфизм буквально означает множественные формы. (или много форм): Объект из разных классов и с тем же именем метода, но рабочие процессы разные. Простой пример будет:
Рассмотрим человека X.
Он только один человек, но он действует как многие. Вы можете спросить, как:
Он сын своей матери. Друг своим друзьям. Брат его сестре.
Полиморфизм - это способность программиста писать методы с одинаковыми именами, которые делают разные вещи для разных типов объектов, в зависимости от потребностей этих объектов. Например, если вы разрабатывали класс с именем Fraction
и класс под названием ComplexNumber
оба они могут включать метод display()
, но каждый из них реализовал бы этот метод по-своему. В PHP, например, вы можете реализовать это так:
// Class definitions
class Fraction
{
public $numerator;
public $denominator;
public function __construct($n, $d)
{
// In real life, you'd do some type checking, making sure $d != 0, etc.
$this->numerator = $n;
$this->denominator = $d;
}
public function display()
{
echo $this->numerator . '/' . $this->denominator;
}
}
class ComplexNumber
{
public $real;
public $imaginary;
public function __construct($a, $b)
{
$this->real = $a;
$this->imaginary = $b;
}
public function display()
{
echo $this->real . '+' . $this->imaginary . 'i';
}
}
// Main program
$fraction = new Fraction(1, 2);
$complex = new ComplexNumber(1, 2);
echo 'This is a fraction: '
$fraction->display();
echo "\n";
echo 'This is a complex number: '
$complex->display();
echo "\n";
Выходы:
This is a fraction: 1/2
This is a complex number: 1 + 2i
Некоторые из других ответов, по-видимому, подразумевают, что полиморфизм используется только в сочетании с наследованием; например, может быть Fraction
а также ComplexNumber
оба реализуют абстрактный класс под названием Number
у этого есть метод display()
, которые Fraction и ComplexNumber затем оба обязаны реализовать. Но вам не нужно наследование, чтобы воспользоваться преимуществами полиморфизма.
По крайней мере, в динамически типизированных языках, таких как PHP (я не знаю о C++ или Java), полиморфизм позволяет разработчику вызывать метод, не зная заранее типа объекта, и полагая, что правильная реализация метода будет называться. Например, скажем, пользователь выбирает тип Number
создано:
$userNumberChoice = $_GET['userNumberChoice'];
switch ($userNumberChoice) {
case 'fraction':
$userNumber = new Fraction(1, 2);
break;
case 'complex':
$userNumber = new ComplexNumber(1, 2);
break;
}
echo "The user's number is: ";
$userNumber->display();
echo "\n";
В этом случае соответствующий display()
будет вызван метод, даже если разработчик не может заранее знать, выберет ли пользователь дробь или комплексное число.
Что такое полиморфизм?
Полиморфизм - это способность:
Вызов операции над экземпляром специализированного типа, зная только его обобщенный тип при вызове метода специализированного типа, а не метода обобщенного типа: это динамический полиморфизм.
Определите несколько методов с именем сохранения, но с разными параметрами: это статический полиморфизм.
Первое, если историческое определение, и самое главное.
Для чего используется полиморфизм?
Это позволяет создавать строго типизированную согласованность иерархии классов и делать некоторые волшебные вещи, такие как управление списками объектов разных типов, не зная их типы, но только один из их родительского типа, а также привязки данных.
Образец
Вот некоторые фигуры, такие как Point, Line, Rectangle и Circle, у которых операция Draw() не принимает ничего или не использует параметр для установки тайм-аута для его удаления.
public class Shape
{
public virtual void Draw()
{
DoNothing();
}
public virtual void Draw(int timeout)
{
DoNothing();
}
}
public class Point : Shape
{
int X, Y;
public override void Draw()
{
DrawThePoint();
}
}
public class Line : Point
{
int Xend, Yend;
public override Draw()
{
DrawTheLine();
}
}
public class Rectangle : Line
{
public override Draw()
{
DrawTheRectangle();
}
}
var shapes = new List<Shape> { new Point(0,0), new Line(0,0,10,10), new rectangle(50,50,100,100) };
foreach ( var shape in shapes )
shape.Draw();
Здесь класс Shape и методы Shape.Draw() следует пометить как абстрактные.
Они не для того, чтобы понимать.
Объяснение
Без полиморфизма с использованием abstract-virtual-override при синтаксическом анализе фигур вызывается только метод Spahe.Draw(), поскольку среда CLR не знает, какой метод вызывать. Таким образом, он вызывает метод типа, с которым мы работаем, и здесь типом является Shape из-за объявления списка. Так что код вообще ничего не делает.
Благодаря полиморфизму среда CLR может определить реальный тип объекта, с которым мы действуем, используя так называемую виртуальную таблицу. Поэтому он вызывает хороший метод, и здесь вызов Shape.Draw(), если Shape равен Point, вызывает Point.Draw(). Итак, код рисует фигуры.
Больше чтения
Полиморфизм в Java (уровень 2)
Полиморфизм позволяет одной и той же рутине (функции, методу) воздействовать на разные типы.
Поскольку во многих существующих ответах субтипирование смешивается с полиморфизмом, существует три способа (включая субтипирование) для реализации полиморфизма.
- Параметрический (универсальный) полиморфизм позволяет подпрограмме принимать один или несколько параметров типа, в дополнение к нормальным параметрам, и запускается для этих типов самостоятельно.
- Полиморфизм подтипа позволяет подпрограмме воздействовать на любой подтип своих параметров.
- Специальный полиморфизм обычно использует обычную перегрузку для предоставления полиморфного поведения, но может также ссылаться на другие реализации полиморфизма.
Смотрите также:
http://wiki.c2.com/?CategoryPolymorphism
https://en.wikipedia.org/wiki/Polymorphism_(computer_science)
Во-первых, я считаю, что полиморфизм — это неотъемлемая часть объектно-ориентированного программирования, которая позволяет нам определять поведение, общее для нескольких классов, но может быть изменено для каждого класса отдельно. Я хотел бы поделиться кое-чем из своего опыта, чтобы помочь на простых примерах, как уменьшить сложность кода.
Я могу понять, что в некотором смысле это может быть конструктивно для повторного использования кода и сохранения части удобства сопровождения. Это делает их менее болезненными. Но, как и любой другой метод программирования, бывают случаи, когда полиморфизм может оказаться не лучшим вариантом.
Рассмотрим базовый класс, вызываемый с помощью вызываемого метода, который сообщает движку, как запуститься. Предположим, у вас есть производные классы, такие как и . В этом случае вы можете использовать полиморфизм, чтобы определить метод в базовом классе, а затем переопределить этот метод в производных классах, чтобы обеспечить конкретную реализацию для каждого типа автомобиля. Но это может привести к неприятностям. Давайте рассмотрим код.
/// <summary>
/// Base class for car objects
/// </summary>
public abstract class Car
{
public virtual void StartEngine()
{
Console.WriteLine(value: "Car engine has been started.");
}
public virtual void StopEngine()
{
Console.WriteLine(value: "Car engine has been stopped.");
}
}
Как только мы определили базовый класс, давайте определим производные классы.
/// <summary>
/// Example of polymorphism in C# using abstract classes on Mercedes Benz cars
/// </summary>
public class MercedesBenzCar : Car
{
public override void StartEngine()
{
Console.WriteLine(value: "Turning on the ignition and starting the Mercedes-Benz S Class...");
}
public override void StopEngine()
{
Console.WriteLine(value: "Turning off the ignition and stopping the Mercedes-Benz S Class...");
}
}
/// <summary>
/// Example of polymorphism in C# using abstract classes on Tesla Electric Cars
/// </summary>
public sealed class TeslaModelSCar : Car
{
public override void StartEngine()
{
Console.WriteLine(value: "The electric motor in the Tesla Model S car was activated...");
}
public override void StopEngine()
{
Console.WriteLine(value: "The electric motor in the Tesla Model S car was deactivated...");
}
}
Так в чем смысл? В этом примере методы и базового класса показывают, как завести машину и, по сути, запустить или остановить ее. и классы переопределяют эти методы, чтобы обеспечить свои реализации поведения, уникального для электрических и топливных автомобилей соответственно. Таким образом, имеет смысл определять поведение непосредственно в производных классах, а не использовать полиморфизм для его описания в базовом классе.
Как видите, такой дизайн может быть не очень хорошей идеей, если методы или ведут себя по-разному в каждом производном классе. Это связано с тем, что потребовалось бы много работы, чтобы определить осмысленную реализацию методов или в базовом классе. В этом случае может быть лучше напрямую определить метод или в производных классах вместо использования полиморфизма.
Как мы можем найти решение этой проблемы?
Давайте еще раз посмотрим на этот пример и посмотрим, как наследование и полиморфизм можно использовать в C#, когда поведение производных классов сильно отличается.
Что касается рефакторинга, я хотел бы предложить ввести интерфейсы или контракты в качестве потенциального решения этой проблемы и дать нам лучший дизайн. Прежде чем говорить об интерфейсах, давайте рассмотрим, что они из себя представляют. Выводы можно рассматривать как предложения для класса или структуры, которые описывают их свойства и методы.
Новая версия C# может иметь реализации по умолчанию, но давайте не будем усложнять ситуацию. Если вы хотите узнать об этом больше, перейдите по этой ссылке. Короче говоря, они говорят о том, как должны выглядеть подписи участников, но не о том, как должна выглядеть реализация.
Я хотел бы предложить, чтобы интерфейс определял два метода,
Почему? Это может быть более гибким и устойчивым дизайном, чем наследование, потому что вы можете добавлять или удалять интерфейсы из класса, не затрагивая иерархию наследования классов. Давайте теперь рефакторим наше вышеприведенное решение, чтобы увидеть его на практике.
/// <summary>
/// Base interface for all car types.
/// </summary>
public interface ICar
{
/// <summary>
/// Use this method to turn on the car engine.
/// </summary>
void StartEngine();
/// <summary>
/// Use this method to turn off the car engine.
/// </summary>
void StopEngine();
}
Один раз интерфейс
/// <summary>
/// Example of using the interface ICar for the class TeslaModelSCar.
/// </summary>
public sealed class TeslaModelSCar : ICar
{
public void StartEngine()
{
Console.WriteLine(value: "The electric motor in the Tesla Model S car was activated...");
}
public void StopEngine()
{
Console.WriteLine(value: "The electric motor in the Tesla Model S car was deactivated...");
}
}
/// <summary>
/// Example of using the interface ICar for the class MercedesBenzCar.
/// </summary>
public class MercedesBenzCar : ICar
{
public void StartEngine()
{
Console.WriteLine(value: "Turning on the ignition and starting the Mercedes-Benz S Class...");
}
public void StopEngine()
{
Console.WriteLine(value: "Turning off the ignition and stopping the Mercedes-Benz S Class...");
}
}
Процесс рефакторинга завершен. Теперь пришло время посмотреть, как его использовать.
ICar teslaModelS = new TeslaModelSCar();
ICar mercedesBenz = new MercedesBenzCar();
teslaModelS.StartEngine();
mercedesBenz.StartEngine();
Console.WriteLine(value: "Press any key to stop engines...");
Console.ReadLine();
teslaModelS.StopEngine();
mercedesBenz.StopEngine();
await Task.Delay(delay: TimeSpan.FromSeconds(value: 3)); // Wait for 3 seconds in order to see the output
Представьте на мгновение, что у нас есть коллекция автомобилей в гараже и есть другой способ использовать ее для запуска двигателей автомобилей в последовательном порядке.
var carsInGarage = new ICar[2] { new TeslaModelSCar(), new MercedesBenzCar() };
foreach (var car in carsInGarage)
{
car.StartEngine();
}
Console.WriteLine(value: "Press any key to stop engines...");
Console.ReadLine();
foreach (var car in carsInGarage)
{
car.StopEngine();
}
await Task.Delay(delay: TimeSpan.FromSeconds(value: 3)); // Wait for 3 seconds in order to see the output
Опять же, полиморфизм — это мощный метод объектно-ориентированного программирования, который позволяет вам определять поведение, совместно используемое более чем одним классом. Но, как и любой другой метод программирования, бывают случаи, когда полиморфизм может оказаться не лучшим вариантом. Я считаю, что есть ситуации, когда мы должны рассмотреть интерфейс:
- Когда поведение класса сильно отличается от поведения его базового класса. Когда есть много классов, которые основаны на нем.
- Когда важна производительность.
- Когда вам нужно поддерживать более одного наследования, поскольку C# не делает этого сам по себе.
Принимая решение о том, использовать ли полиморфизм в вашем коде, я считаю важным помнить об этих вещах.
Ваше здоровье!
Полиморфизм - это способность использовать объект в данном классе, где все компоненты, составляющие объект, наследуются подклассами данного класса. Это означает, что, как только этот объект объявлен классом, все подклассы ниже его (и их подклассы, и так далее, пока вы не достигнете самого дальнего / самого нижнего подкласса) наследуют объект и его компоненты (косметику).
Помните, что каждый класс должен быть сохранен в отдельных файлах.
Следующий код иллюстрирует полиморфизм:
Суперкласс:
public class Parent {
//Define things that all classes share
String maidenName;
String familyTree;
//Give the top class a default method
public void speak(){
System.out.println("We are all Parents");
}
}
Отец, подкласс:
public class Father extends Parent{
//Can use maidenName and familyTree here
String name="Joe";
String called="dad";
//Give the top class a default method
public void speak(){
System.out.println("I am "+name+", the father.");
}
}
Ребенок, другой подкласс:
public class Child extends Father {
//Can use maidenName, familyTree, called and name here
//Give the top class a default method
public void speak(){
System.out.println("Hi "+called+". What are we going to do today?");
}
}
Метод выполнения ссылается на родительский класс для запуска:
public class Parenting{
public static void main(String[] args) {
Parent parents = new Parent();
Parent parent = new Father();
Parent child = new Child();
parents.speak();
parent.speak();
child.speak();
}
}
Обратите внимание, что каждый класс должен быть объявлен в отдельных *.java файлах. Код должен скомпилироваться. Также обратите внимание, что вы можете постоянно использовать maidenName и familyTree дальше вниз. Это концепция полиморфизма. Концепция наследования также исследуется здесь, где один класс может быть использован или определяется подклассом.
Надеюсь, что это помогает и проясняет. Я опубликую результаты, когда найду компьютер, который смогу использовать для проверки кода. Спасибо за терпение!
В объектно-ориентированных языках полиморфизм позволяет обрабатывать и обрабатывать различные типы данных через один и тот же интерфейс. Например, рассмотрим наследование в C++: класс B является производным от класса A. Указатель типа A* (указатель на класс A) может использоваться для обработки как объекта класса A, так и объекта класса B.
Полиморфизм дает вам возможность создавать один модуль, вызывающий другой, и в то же время иметь точку зависимости времени компиляции от потока управления, а не от потока управления.
При использовании полиморфизма модуль высокого уровня не зависит от модуля низкого уровня. Оба зависят от абстракций. Это помогает нам применять принцип инверсии зависимостей ( https://en.wikipedia.org/wiki/Dependency_inversion_principle).
Вот где я нашел приведенное выше определение. Примерно через 50 минут видео инструктор объясняет вышеизложенное. https://www.youtube.com/watch?v=TMuno5RZNeE
Полиморфизм в терминах кодирования - это когда ваш объект может существовать в виде нескольких типов посредством наследования и т. Д. Если вы создаете класс с именем "Shape", который определяет количество сторон вашего объекта, то вы можете затем создать новый класс, который наследует его, например, "Квадрат". ". Когда вы впоследствии создадите экземпляр "Квадрата", вы можете затем повернуть его назад и вперед из "Формы" в "Квадрат", как требуется.