Полиморфизм (информатика)

редактировать

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

Наиболее широко признанный основной классами полиморфизма являются:

  • Специальный полиморфизм : определяет общий интерфейс для произвольного набора индивидуально указанных типов.
  • Параметрический полиморфизм : когда один или несколько типов указаны не по имени, а по абстрактному символы, которые могут представлять любой тип.
  • Подтип (также называемый полиморфизмом подтипа или полиморфизмом включения): когда имя обозначает экземпляры многих различных классов, связанных некоторым общим суперклассом.
Содержание
  • 1 История
  • 2 Типы
    • 2.1 Специальный полиморфизм
    • 2.2 Параметрический полиморфизм
    • 2.3 Подтипирование
    • 2.4 Полиморфизм строк
    • 2.5 Политипизм
  • 3 Аспекты реализации
    • 3.1 Статический и динамический полиморфизм
  • 4 См. Также
  • 5 Ссылки
  • 6 Внешние ссылки
История

Интерес к полиморфным системам типов значительно вырос в 1960-х годах, с практическими реализациями, которые начинают появляться к концу десятилетия. Специальный полиморфизм и параметрический полиморфизм были первоначально описаны в Christopher Strachey «Основные концепции языков программирования », где они перечислены как «два основных класса» полиморфизма. Специальный полиморфизм был особенностью Algol 68, в то время как параметрический полиморфизм был ключевой особенностью системы типов ML.

В статье 1985 года Питер Вегнер и Лука Карделли ввели термин «полиморфизм включения» для моделирования подтипов и наследования, ссылаясь на Simula как первый язык программирования, который его реализовал.

Типы

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

Кристофер Стрейчи выбрал термин специальный полиморфизм для обозначения полиморфных функций, которые могут применяться к аргументам разных типов, но ведут себя по-разному в зависимости от от типа аргумента, к которому они применяются (также известный как перегрузка функции или перегрузка оператора ). Термин «ad hoc » в данном контексте не предназначен для уничижительного отношения; это просто относится к тому факту, что этот тип полиморфизма не является фундаментальной особенностью системы типов. В приведенном ниже примере Pascal / Delphi функции Add, похоже, работают в общем над различными типами при просмотре вызовов, но считаются двумя совершенно разными функции компилятора для всех целей и задач:

программа Adhoc; функция Add (x, y: Integer): Integer; начало Добавить: = x + y конец; функция Add (s, t: String): String; begin Добавить: = Concat (s, t) end; начать Writeln (Добавить (1, 2)); (* Выводит "3" *) Writeln (Add ('Hello,', 'Mammals!')); (* Выводит «Здравствуйте, млекопитающие!» *) End.

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

Неявное преобразование типов также определяется как форма полиморфизма, называемая «полиморфизмом принуждения».

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

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

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

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

список данных a = Nil | Минусы a (List a) length :: List a ->Integer length Nil = 0 length (Cons x xs) = 1 + length xs map :: (a ->b) ->List a ->List b map f Nil = Nil map f (Cons x xs) = Cons (fx) (map f xs)

Параметрический полиморфизм также доступен в нескольких объектно-ориентированных языках. Например, шаблоны в C ++ и D или под именем generics в C #, Delphi и Java:

class List {class Node {T elem ; Узел следующий; } Узел голова; int length () {...}} List map (Func f, List xs) {...}

Джон С. Рейнольдс (и позже Жан -Ив Жирар ) формально развил это понятие полиморфизма как расширение лямбда-исчисления (названного полиморфным лямбда-исчислением или Системой F ). Любая параметрически полиморфная функция обязательно ограничена в том, что она может делать, работая с формой данных вместо их значения, что приводит к концепции параметричности.

подтипов

Некоторые языки используют идею выделение подтипов (также называемое полиморфизмом подтипа или полиморфизмом включения) для ограничения диапазона типов, которые могут использоваться в конкретном случае полиморфизма. В этих языках подтипирование позволяет записать функцию, которая принимает объект определенного типа T, но также работает правильно, если передан объект, принадлежащий к типу S, который является подтипом T (согласно Лискову принцип замещения ). Это отношение типов иногда обозначается как S <: T. Conversely, T is said to be a supertype of S—written T :>S. Полиморфизм подтипа обычно разрешается динамически (см. Ниже).

В следующем примере мы делаем кошек и собак подтипами животных. Процедура LetHear ()принимает животное, но также будет работать правильно, если ей передан подтип:

абстрактный класс Animal {abstract String talk (); } class Cat расширяет Animal {String talk () {return "Meow!"; }} class Dog расширяет Animal {String talk () {return "Woof!"; }} static void letHear (final Animal a) {println (a.talk ()); } static void main (String args) {letHear (new Cat ()); LetHear (новая собака ()); }

В другом примере, если Number, Rational и Integer являются такими типами, что Number:>Rational и Number:>Integer, функция, записанная для приема числа, будет работать одинаково хорошо при передаче Integer или Rational, как и при передаче Номер. Фактический тип объекта может быть скрыт от клиентов в черном ящике и доступен через объект identity. Фактически, если тип Number является абстрактным, может быть даже невозможно получить в руки объект, наиболее производным типом которого является Number (см. абстрактный тип данных, абстрактный класс ). Этот конкретный вид иерархии типов известен - особенно в контексте языка программирования Scheme - как числовая башня и обычно содержит гораздо больше типов.

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

  • позднего связывания, поскольку вызовы виртуальных функций не привязываются до момента вызова;
  • одиночной отправки (т.е. полиморфизм с одним аргументом), поскольку вызовы виртуальных функций связаны простым просмотром таблицы vtable, предоставленной первым аргументом (объект this), поэтому типы времени выполнения других аргументов совершенно не важны.

То же самое касается большинства других популярных объектных систем. Некоторые, однако, такие как Common Lisp Object System, предоставляют множественную отправку, при которой вызовы методов полиморфны по всем аргументам.

Взаимодействие между параметрическим полиморфизмом и подтипами приводит к концепциям дисперсии и ограниченной количественной оценки.

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

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

Политипизм

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

Аспекты реализации

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

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

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

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

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

См. Также
Ссылки
Внешние ссылки
Последняя правка сделана 2021-06-02 10:34:05
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте