Постарайтесь описать полиморфизм как можно проще [закрыто]

StackOverflow https://stackoverflow.com/questions/210460

Вопрос

Как можно описать полиморфизм простым для понимания способом?

Мы можем найти много информации по этому вопросу в Интернете и книгах, например, в Тип полиморфизма.Но давайте попробуем сделать это как можно проще.

Это было полезно?

Решение

Это из моего отвечать из аналогичного вопроса.Вот пример полиморфизма в псевдо-C#/Java:

class Animal
{
    abstract string MakeNoise ();
}

class Cat : Animal {
    string MakeNoise () {
        return "Meow";
    }
}

class Dog : Animal {
    string MakeNoise () {
        return "Bark";
    }
}

Main () {
   Animal animal = Zoo.GetAnimal ();
   Console.WriteLine (animal.MakeNoise ());
}

Метод Main() не знает тип животного и зависит от поведения конкретной реализации метода MakeNoise().

Другие советы

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

Каждая банка с простой крышкой открывается одинаково.
Как человек, вы знаете, что можете использовать Open() любой такой метод, который сможете найти.

При открытии не все банки ведут себя одинаково.
Некоторые содержат орехи, некоторые — выскакивающих искусственных змей.
Результат зависит от ТИП банки, если она была «CanOfNuts» или «CanOfSnakes», но это не имеет никакого отношения к тому, КАК вы ее открываете.Вы просто знаете, что можете открыть любую банку и получите некий результат, который определяется в зависимости от типа банки, которую вы открыли.

pUnlabledCan->Открыть();//может дать орехи, может дать змей.Мы не знаем, пока не назовем это

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

Вы, человек, являетесь пользователем/звонящим.
Open() — виртуальная/полиморфная функция.
«Может» — это абстрактный базовый класс.
CanOfNuts и CanOfSnakes — полиморфные дочерние элементы класса Can.
Любую банку можно открыть, но что именно? делает и какой конкретно тип содержание его возвраты определяются тем, какой это тип банки.
Все, что вы знаете, когда видите pUnlabledCan, это то, что вы можете открыть его(), и он вернет содержимое.Любое другое поведение (например, бросок змей вам в лицо) определяется конкретным Can.

Простейшее описание полиморфизма состоит в том, что это способ сократить операторы if/switch.

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

Например, рассмотрим Stream класс в .NET.Без полиморфизма это был бы один массивный класс, в котором каждый метод реализует оператор переключения, например:

public class Stream
{
    public int Read(byte[] buffer, int offset, int count)
    {
        if (this.mode == "file")
        {
            // behave like a file stream
        }
        else if (this.mode == "network")
        {
            // behave like a network stream
        }
        else // etc.
    }
}

Вместо этого мы позволяем среде выполнения выполнять переключение за нас более эффективным способом, автоматически выбирая реализацию на основе конкретного типа (FileStream, NetworkStream), например

public class FileStream : Stream
{
    public override int Read(byte[] buffer, int offset, int count)
    {
        // behave like a file stream
    }
}

public class NetworkStream : Stream
{
    public override int Read(byte[] buffer, int offset, int count)
    {
        // behave like a network stream
    }
}

Поли:много
Морфизм:формы / формы

Актер против.Персонаж (или роль)

Яблоки и апельсины — это фрукты.Фрукты можно есть.Следовательно, можно есть и яблоки, и апельсины.

Кикер?Вы едите их по-другому!Вы чистите апельсины, но не яблоки.

Таким образом, реализация отличается, но конечный результат тот же. ты ешь фрукты.

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

На самом деле это лучшая статья

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

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

Тот же синтаксис, другая семантика.

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

Все остальное, как сказал Гилель, — всего лишь комментарий.

Полиморфизм рассматривает вещи абстрактно, полагаясь на знание общего «родителя» (представьте себе такие иерархии, как «Животное», как родителя «Собаки» и «Кошки»).

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

В качестве небольшого дополнения вы можете сделать это, даже если Animal является «абстрактным» идентификатором (настоящего «Животного» не существует, есть только типы животных).

Полиморфизм — это хранение значений более чем одного типа в месте одного типа.

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

Динамическая отправка требует полиморфизма, но обратное неверно.Можно представить себе язык, очень похожий на Java или C#, но в котором System.Object не имеет членов;прежде чем что-либо делать со значением, потребуется приведение типов.В этом условном языке будет присутствовать полиморфизм, но не обязательно виртуальные методы или какие-либо другие механизмы динамической диспетчеризации.

Динамическая диспетчеризация — это связанная, но отдельная концепция, достаточно хорошо описанная в большинстве других ответов.Однако то, как это обычно работает в объектно-ориентированных языках (выбор функции на основе первого типа аргумента («this» или «Self»), — не единственный способ, которым это может работать. Множественная отправка также возможно, когда выбор применяется к типам всех аргументов.

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

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

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

Полиморфизм — это то, что вы получаете, когда один и тот же метод применяется к нескольким классам.Например, и строка, и список могут иметь «обратные» методы.Оба метода имеют одинаковое название («Реверс»).Оба метода делают что-то очень похожее (переворачивают все символы или меняют порядок элементов в списке).Но реализация каждого метода «Reverse» различна и специфична для своего класса.(Другими словами, String инвертируется как строка, а List инвертируется как список.)

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

Практический результат заключается в том, что вы можете создать «Реверсивный механизм», который принимает объект и вызывает для него «Реверс».Пока у объекта есть метод Reverse, ваш реверсивный механизм будет работать.

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

Это дает вам как программисту меньшее количество строк кода и либо безопасность типов, либо позднее связывание.Например, вот пример с безопасностью типов и ранним связыванием (на языке C, который я придумываю по ходу дела):

class BankAccount {
    void SubtractMonthlyFee
}

class CheckingAccount : BankAccount {}

class SavingsAccount : BankAccount {}

AssessFee(BankAccount acct) {
    // This will work for any class derived from
    //   BankAccount; even classes that don't exist yet
    acct.SubtractMonthlyFee
}

main() {

    CheckingAccount chkAcct;
    SavingsAccount saveAcct;

    // both lines will compile, because both accounts
    //   derive from "BankAccount". If you try to pass in
    //   an object that doesn't, it won't compile, EVEN
    //   if the object has a "SubtractMonthlyFee" method.
    AssessFee(chkAcct);
    AssessFee(saveAcct);
}

Вот пример без типовой безопасности, но с поздним связыванием:

class DatabaseConnection {
    void ReleaseResources
}

class FileHandle {
    void ReleaseResources
}

FreeMemory(Object obj) {
    // This will work for any class that has a 
    //   "ReleaseResources" method (assuming all
    //   classes are ultimately derived from Object.
    obj.ReleaseResources
}

main() {

    DatabaseConnection dbConn;
    FileHandle fh;

    // You can pass in anything at all and it will
    //   compile just fine. But if you pass in an
    //   object that doesn't have a "ReleaseResources"
    //   method you'll get a run-time error.
    FreeMemory(dbConn);
    FreeMemory(fh);
    FreeMemory(acct); //FAIL! (but not until run-time)
}

Отличный пример — метод .NET ToString().Он есть у всех классов, поскольку все классы являются производными от класса Object.Но каждый класс может реализовать ToString() способом, который имеет для него смысл.

РЕДАКТИРОВАТЬ:Просто!= короче, ИМХО

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

Это достигается путем обеспечения того, чтобы операции вызывали правильную реализацию для каждого типа данных.Даже в контексте ООП (согласно тегу этого вопроса) эта «правильная реализация» может быть решена во время компиляции или во время выполнения (если ваш язык поддерживает оба).В некоторых языках, таких как C++, компилятор поддерживает полиморфизм во время выполнения (т.виртуальная диспетчеризация) специфична для ООП, тогда как другие типы полиморфизма также могут работать с типами данных, которые не являются объектами (т.е.нет struct или class экземпляры, но могут быть встроенными типами, такими как int или double).

(Типы полиморфизма, поддерживаемые C++, перечислены и сопоставлены в моем ответе: Полиморфизм в С++ - даже если вы программируете на других языках, это потенциально поучительно)

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

interface IJobLoader

но в зависимости от того, как он используется, он может иметь разные функциональные возможности, но при этом выглядеть одинаково.У вас могут быть экземпляры BatchJobLoader, NightlyJobLoader и т. д.

Может быть, я далеко.

Термин полиморфизм также может применяться к перегрузке функций.Например,

string MyFunc(ClassA anA);
string MyFunc(ClassB aB);

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

Это способность объектов реагировать на одно и то же сообщение по-разному.

Например, в таких языках, как smalltalk, Ruby, Objective-C, вам просто нужно отправить сообщение, и они ответят.

 dao  = XmlDao.createNewInstance()    #obj 1
 dao.save( data )

 dao = RdbDao.createNewnewInstance()  #obj 2
 dao.save( data )

В этом примере два разных объекта по-разному ответили на одни и те же сообщения:«createNewInstance() и сохранить(obj)»

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

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

легкий ..и простой.

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

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

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

foreach (Vehicle v in Game.Vehicles)
{
   v.Stop();
}

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

Это просто способ остудить вызов нового кода.Вы пишете какое-то приложение, которое принимает некоторый интерфейс «Shape» с методами, которые должны реализовать другие (пример — getArea).Если кто-то придумает новый способ реализации этого интерфейса, ваш старый код сможет вызвать этот новый код через метод getArea.

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

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

 void h() { float x=3.0; printf("%f", x); }
 void k() { int y=5; printf("%i", y); }
 void g(void (*f)()) { f(); }
 g(h);  // output 3.0
 g(k);  // output 5

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

 void h(void *a) { float* x=(float*)a; printf("%f",*x); }
 void k(void *a) { int* y=(int*)a; printf("%i",*y); }
 void g(void (*f)(void *a),void *a) { f(a); }
 float x=3.0;
 int y=5;
 g(h,&x); // output x
 g(k,&y); // output y

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

class Base { virtual public void call()=0; }
class H : public Base { float x; public void call() { printf("%f",x);} } h;
class K : public Base { int y; public void call() { printf("%i",y);} } k;
void g(Base &f) { f.call(); };
h.x=3.0;
k.y=5;
g(h); // output h.x
g(k); // output k.x
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top