Принадлежит ли интерфейс специальному полиморфизму (то есть перегрузке) или полиморфизму подтипа?
https://wiki.haskell.org/Polymorphism говорит
Специальный полиморфизм относится к случаю, когда значение может принимать любой из нескольких типов, потому что ему или используемому значению было дано отдельное определение для каждого из этих типов. Например, оператор +, по сути, делает что-то совершенно иное, когда применяется к значениям с плавающей запятой, по сравнению с тем, когда применяется к целым числам - в Python его можно применять и к строкам. Большинство языков поддерживают, по крайней мере, некоторый специальный полиморфизм, но в таких языках, как C, он ограничен только встроенными функциями и типами. Другие языки, такие как C++, позволяют программистам обеспечивать свою собственную перегрузку, предоставляя множество определений одной функции, для устранения неоднозначности по типам аргументов. В Haskell это достигается с помощью системы классов типов и экземпляров классов.
Несмотря на сходство названия, классы типов Хаскелла весьма отличаются от классов большинства объектно-ориентированных языков. Они имеют больше общего с интерфейсами в том смысле, что они определяют серию методов или значений по сигнатуре типа, которые должны быть реализованы в объявлении экземпляра.
Означает ли это, что классы типов являются способом достижения перегрузки, то есть специального полиморфизма?
К какому полиморфизму относится интерфейс в ОО-языках (например, Java, C#), специальный полиморфизм (т. Е. Перегрузка) или полиморфизм подтипа?
Так как класс типов подобен интерфейсу, является ли интерфейс способом перегрузки, то есть специальным полиморфизмом, так же, как класс типов?
Является ли интерфейс похожим на базовый класс, и является ли интерфейс способом достижения полиморфизма подтипа, так же как и наследование классов?
Благодарю.
1 ответ
Типы не имеют иерархии типов, но классы типов имеют.
Я бы не думал о классах типов как о наследовании классов, потому что у вас нет родительской структуры, у вас есть только подпись. Их можно рассматривать как классические интерфейсы языков ООП, вроде...
Но в цитируемом вами тексте говорится:
Например,
(+)
Оператор, по сути, делает что-то совершенно иное, когда применяется к значениям с плавающей точкой по сравнению с тем, когда применяется к целым числам
Что-то такое простое как (+)
функция, с типами не так.
У вас есть TypeClass
иерархия Num
уважать. Например
plus :: Num a => a -> a -> a
plus x y = x + y
и у вас есть (я могу сосчитать) четыре прямых подтипа Integral
(реализовано Int
а также Integral
) а также Fractional
(реализовано Float
а также Double
). Integral
а также Fractional
классы типов являются подтипами Num
класс типов.
Итак, посмотрите на подписи этого типа функции:
(/) :: Fractional a => a -> a -> a
(div) :: Integral a => a -> a -> a
(+) :: Num a => a -> a -> a
каждый из них имеет свою собственную реализацию и ограничивает тип данных, который вы можете использовать в иерархиях типов подтипов и супертипов, всегда говоря о Typeclass
а не сам тип.
Об отношениях с ООП:
В Java, например, типы и классы - это разные вещи. Смотреть:
List<String> xs = new ArrayList<>();
List<String> ys = new LinkedList<>();
xs.add("Haskell");
ys.add("Forever");
Тип там есть List
, но поведение этих списков определяется классом (ArrayList или LinkedList). И даже больше, вы можете сделать:
ArrayList<String> ls = new ArrayList<>();
ls.add("something);
Действительно, тип и класс совпадают.
С другой стороны, в Haskell это не так, (+)
Поведение метода задается реализацией типа в соответствии с его классом типов.
Есть пример классического полезного Typeclass
иерархия в Хаскеле: