Объясните полиморфизм

Что такое полиморфизм? Я не уверен, что правильно понимаю.

В области Python я получаю от этого то, что могу определять параметры следующим образом:

def blah (x, y)

без необходимости указывать тип, в отличие от другого языка, такого как Java, где он будет выглядеть примерно так:

public void blah (int x, string y)

Я правильно понял?


person TopChef    schedule 23.07.2010    source источник
comment
Я не уверен, что вы пытаетесь описать, но это не полиморфизм... не могли бы вы уточнить, что вы хотите знать?   -  person Thomas Owens    schedule 24.07.2010
comment
Это пример полиморфизма, но большинство людей ссылаются на вариации арности и типа метода (с тем же именем метода) как на основное определение.   -  person Jon Bringhurst    schedule 24.07.2010
comment
Я не знаю Python, но для меня это не похоже на полиморфизм.   -  person kirk.burleson    schedule 24.07.2010
comment
@John Bringhurst - я думал, что то же имя метода было перегрузкой метода.   -  person kirk.burleson    schedule 24.07.2010
comment
Python не является строго типизированным, как Java, а это означает, что вам не нужно объявлять тип переменной в вашем коде.   -  person derekerdmann    schedule 25.07.2010
comment
@ kirk.burleson Да, многократное объявление одного и того же метода для разных параметров действительно является перегрузкой метода, но здесь обсуждается не это - это метод с параметрами, у которых нет определения типа.   -  person Stephen    schedule 25.07.2010
comment
-1 (Предыдущее исследование не показано) Вы ведь проверили википедию, верно? Кроме того, ваш вопрос больше связан с (динамическим) типом, а не с полиморфизмом.   -  person    schedule 12.12.2010
comment
@derekerdmann Неправильно. Python строго типизирован. Похоже, вы перепутали строгую типизацию со статической типизацией. Либо подождите, это не имеет отношения к специальному полиморфизму (подмножеством которого является утиная типизация и что использует Python).   -  person Wes    schedule 29.07.2012
comment
возможный дубликат Как работает полиморфизм в Python?   -  person Martin Thoma    schedule 18.03.2014


Ответы (11)


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

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

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

  • Другой вид полиморфизма, обычно называемый полиморфизмом ad-hoc или (по крайней мере, для некоторых его форм) обобщенным программированием в функциональном сообществе, и часто полиморфизмом подтипов (хотя это несколько ограничивает концепцию) в сообществе ООП, это способность иметь один метод или функция, которая ведет себя по-разному в зависимости от точного типа своих аргументов (или, для методов, типа объекта, метод которого вызывается). Приведенный выше пример add представляет собой специальный полиморфизм. В динамически типизированных языках эта возможность само собой разумеющаяся; языки со статической типизацией имеют тенденцию (но не должны) иметь ограничения, такие как требование, чтобы аргумент был подклассом некоторого определенного класса (Addable).

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

person Gilles 'SO- stop being evil'    schedule 23.07.2010

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

Полиморфизм

person Truong Ha    schedule 24.07.2010
comment
Полиморфизм не обязательно должен ограничиваться подклассами (как правило, полиморфизм подтипов, но есть и другие виды). Но картинка красивая :-) - person ; 12.12.2010

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

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

def dosomething(thing):
   if type(thing)==suchandsuch:
      #do some stuff
   elif type(thing)==somesuch:
      #do some other stuff
   elif type(thing)==nonesuch:
      #yet more stuff

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

Лучше иметь возможность просто написать:

thing.dosomething()

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

person Tagore Smith    schedule 24.07.2010

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

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

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

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

person Matt    schedule 23.07.2010
comment
Должны ли объекты быть «связаны через цепочку наследования, чтобы быть полиморфными», это не вопрос строгой или слабой типизации, это вопрос номинального или структурного подтипа. Например, в Java есть номинальные подтипы для классов (A является подклассом B, если он является производным от B), но структурные подтипы для интерфейсов (IA является подинтерфейсом B, если он имеет по крайней мере те же методы). Возможны все 8 комбинаций сильного/слабого, статического/динамического, номинального/структурного (не говоря уже о миксах). - person Gilles 'SO- stop being evil'; 24.07.2010

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

Например, Bird и Plane — это FlyingObject. Итак, FlyingObject имеет вызов метода fly(), а Bird и Plane реализуют метод fly(). Bird и Plan летают по-разному, поэтому и реализации разные. С точки зрения клиентов, не имеет значения, как летают Птица или Самолет, они могут просто вызвать метод fly() для объекта FlyingObject, не имеет значения, является ли этот объект Планом или Птицей.

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

Надеюсь на это. НаваМан

person NawaMan    schedule 23.07.2010

Краткий ответ: возможность обрабатывать экземпляры программных типов разных типов как одинаковые для определенных целей.

Длинный ответ: от древнегреческого poly (много) + morph (форма) + -ism.

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

  • parametric polymorphism (рассматривается как дженерики в Java)
  • subtyping polymorphism, реализованный на Java с использованием динамической отправки сообщений между экземплярами объекта.
  • ad-hoc polymorphism, который относится к возможности определять функции с одним и тем же именем, которые различаются только типами, с которыми они имеют дело (перегрузка в Java).

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

person Ben Aston    schedule 23.07.2010

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

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

Например, если у вас есть Vehicle в качестве корневого класса и Car и Bicycle в качестве экземпляров, то Vehicle.calculateDistance() будет работать на основе доступного газа, если транспортное средство является экземпляром Car, и будет работать на основе выносливости велосипедиста, если это был тип велосипеда.

Обычно он используется так:

getTotalDistance(Vehicle[] vehicle) {
    int dist=0
    for each vehicle
        dist+=vehicle.calculateDistance();

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

person Bill K    schedule 23.07.2010

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

Java, C, C++ и другие используют статическую типизацию. При этом вы должны указать, что типы являются временем компиляции.

Python и Ruby используют динамическую логику в том смысле, что типизация выводится во время интерпретации.

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

Например (в почти псевдокоде):

class Base
{
  virtual void Draw() { //base draw}
}

class Derived: public Base
{
  void Draw() { //derived draw}
}

Base* myBasePtr = new Derived();

myBasePtr->Draw(); //invokes Derived::Draw(), even though it's a base pointer.

Это полиморфизм.

person Alan    schedule 23.07.2010
comment
На самом деле в слаботипизированных языках типы неявно полиморфны. - person Jon Bringhurst; 24.07.2010
comment
@Jon: возможно, однако python и ruby ​​слабо типизированы. - person Alan; 24.07.2010
comment
@Alan: То, что вы описали в python, - это не утиная типизация, это динамическая типизация. Утиная типизация, также называемая структурной типизацией, означает (для объектно-ориентированных языков), что объекты имеют одинаковый тип, если они имеют одинаковые методы; противоположность номинальной типизации, когда объекты имеют один и тот же тип, если они были созданы из одного и того же объявления класса (т. е. имя класса одно и то же). - person Gilles 'SO- stop being evil'; 24.07.2010
comment
Это первый раз, когда я вижу, как кто-то описывает C как использующий строгую типизацию. - person Alohci; 24.07.2010
comment
@Alohci: C может не обеспечивать безопасность типов и имеет множество неявных преобразований, но вы не можете волей-неволей смешивать типы. - person Alan; 24.07.2010
comment
Может показаться (через поиск в Google), что существует несколько определений строгой/слабой типизации. Интересно. - person Jon Bringhurst; 24.07.2010
comment
Я думаю, что различие, которое вы ищете, - это не сильная и слабая типизация, а статическая типизация против динамической типизации. Статическая типизация имеет некоторые большие преимущества, когда речь идет о статическом анализе вашего кода — инструменты имеют полное представление о вашей системе в любой момент времени. Динамические типы могут изменяться в зависимости от контекста среды выполнения, поэтому их легче видоизменять, но это значительно упрощает взлом — вы часто можете проделывать некоторые действительно забавные трюки с языками с динамической типизацией. - person Bill K; 24.07.2010

Полиморфизм:

  • Один вызов метода работает с несколькими классами, даже если классы нуждаются в разных реализациях;
  • Возможность предоставить несколько реализаций действия и выбрать правильную реализацию на основе окружающего контекста;
  • Обеспечивает перегрузку и переопределение;
  • Could occurs both in Runtime and Compile-Time;
      1. Run time Polymorphism : Run time Polymorphism also known as method overriding Method overriding means having two or more methods with the same name , same signature but with different implementation
      1. Compile time Polymorphism : Compile time Polymorphism also known as method overloading Method overloading means having two or more methods with the same name but with different signatures
  • В компьютерных науках полиморфизм — это функция языка программирования, которая позволяет обрабатывать значения различных типов данных с использованием единого интерфейса. Концепция параметрического полиморфизма применяется как к типам данных, так и к функциям. Функция, которая может оцениваться или применяться к значениям разных типов, известна как полиморфная функция. Тип данных, который может выглядеть как обобщенный тип (например, список с элементами произвольного типа), называется полиморфным типом данных, как и обобщенный тип, из которого сделаны такие специализации.
  • Disadvantages of Polymorphism:
    • Polymorphism reduces readability of the program. One needs to visualize runtime behaviour of program to identify actual execution time class involved. It also becomes difficult to navigate through classes implementing this concept. Even sofasticated IDEs can not provide this navigation feature. This adds to the maintainance cost to some extent.
person Malf    schedule 01.02.2016

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

person Eesha    schedule 06.07.2017

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

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

Перегрузка. Перегрузка определяется во время компиляции. Это происходит, когда несколько методов имеют одинаковые имена с:

  1. Другая сигнатура метода и другое количество или тип параметров.
  2. Та же сигнатура метода, но другое количество параметров.
  3. Та же сигнатура метода и то же количество параметров, но другого типа
person EvilInside    schedule 23.07.2010
comment
Извините, этот ответ не имеет смысла. - person grifaton; 24.07.2010