Эта статья требует дополнительных ссылок для проверки . ( июль 2011 г. ) ( Узнайте, как и когда удалить это сообщение-шаблон ) |
Системы типов |
---|
Общие понятия |
Основные категории |
Второстепенные категории |
Смотрите также |
Система структурных типов (или система типов на основе свойств ) - это основной класс систем типов, в которых совместимость и эквивалентность типов определяются фактической структурой или определением типа, а не другими характеристиками, такими как его имя или место объявления. Структурные системы используются, чтобы определить, эквивалентны ли типы и является ли тип подтипом другого. Это контрастирует с номинативными системами , где сравнения основаны на именах типов или явных объявлениях, и с утиной типизацией , в которой только часть структуры, к которой осуществляется доступ во время выполнения, проверяется на совместимость.
Описание [ править ]
При структурной типизации элемент считается совместимым с другим, если для каждой функции в типе второго элемента имеется соответствующая и идентичная функция в первом типе элемента. Некоторые языки могут отличаться по деталям, например, должны ли функции совпадать по названию. Это определение не является симметричным и включает совместимость подтипов. Два типа считаются идентичными, если каждый совместим с другим.
Например, OCaml использует структурную типизацию для методов совместимости типов объектов. Go использует структурную типизацию методов для определения совместимости типа с интерфейсом. Функции шаблонов C ++ демонстрируют структурную типизацию аргументов типа. Haxe использует структурную типизацию, но классы не имеют структурных подтипов.
В языках, которые поддерживают полиморфизм подтипов , подобная дихотомия может быть сформирована на основе того, как определяется отношение подтипов. Один тип является подтипом другого тогда и только тогда, когда он содержит все функции базового типа или его подтипов. Подтип может содержать добавленные функции, такие как элементы, отсутствующие в базовом типе, или более сильные инварианты.
Существует различие между структурной заменой предполагаемого и не предполагаемого полиморфизма. Некоторые языки, такие как Haskell , не выполняют структурную замену в случае, когда ожидаемый тип объявлен (т. Е. Не выведен), например, только заменяют функции, которые являются полиморфными на основе сигнатур посредством вывода типа. [1] Тогда невозможно случайно подтипировать невыявленный тип, хотя все еще может быть возможно обеспечить явное преобразование в невыведенный тип, который вызывается неявно.
Структурное подтипирование, возможно, более гибкое, чем номинативное подтипирование , поскольку оно позволяет создавать специальные типы и протоколы ; в частности, он позволяет создавать тип, который является супертипом существующего типа, без изменения определения последнего. Однако это может быть нежелательно, если программист хочет создавать закрытые абстракции.
Ошибка структурной типизации по сравнению с номинативной типизацией заключается в том, что два отдельно определенных типа, предназначенные для разных целей, но случайно обладающие одинаковыми свойствами (например, оба состоят из пары целых чисел), могут считаться системой типов одним и тем же типом просто потому, что они имеют идентичную структуру. Один из способов избежать этого - создать один алгебраический тип данных для каждого использования.
В 1990 году Кук и др. Доказали, что наследование не является подтипом в объектно-ориентированных языках с структурной типизацией. [2]
Пример [ править ]
Объекты в OCaml структурно типизированы по именам и типам их методов.
Объекты могут быть созданы напрямую ( непосредственные объекты ), не проходя через номинативный класс. Классы служат только как функции для создания объектов.
# let x = object val mutable x = 5 method get_x = x method set_x y = x <- y end ;; значение x : < get_x : int ; set_x : int -> unit > = < объект >
Здесь интерактивная среда выполнения OCaml для удобства распечатывает предполагаемый тип объекта. Его type ( < get_x : int; set_x : int -> unit >
) определяется только его методами. Другими словами, тип x определяется типами методов «get_x: int» и «set_x: int -> unit», а не каким-либо именем. [3]
Чтобы определить другой объект, который имеет те же методы и типы методов:
# let y = object method get_x = 2 method set_x y = Printf . printf "% d \ n " y end ;; val y : < get_x : int ; set_x : int -> unit > = < объект >
OCaml считает их однотипными. Например, оператор равенства набирается так, чтобы принимать только два значения одного типа:
# x = y ;; - : bool = false
Значит, они должны быть одного типа, иначе это даже не проверка типа. Это показывает, что эквивалентность типов структурна.
Можно определить функцию, вызывающую метод:
# let set_to_10 a = a # set_x 10 ;; значение set_to_10 : < set_x : int -> ' a ; .. > -> ' a = < веселье >
Выведенный тип для первого аргумента ( < set_x : int -> 'a; .. >
) интересен. Это ..
означает, что первым аргументом может быть любой объект, у которого есть метод "set_x", который принимает в качестве аргумента int.
Таким образом, его можно использовать на объекте x
:
# set_to_10 x ;; - : unit = ()
Можно создать другой объект, который имеет этот метод и тип метода; остальные методы не имеют значения:
# let z = object method blahblah = 2 . 5 метод set_x y = Printf . printf "% d \ n " y end ;; val z : < blahblah : float ; set_x : int -> unit > = < объект >
С ним также работает функция "set_to_10":
# set_to_10 z ;; 10 - : единица = ()
Это показывает, что совместимость таких вещей, как вызов метода, определяется структурой.
Давайте определим синоним типа для объектов только с помощью метода get_x и без других методов:
# type simpler_obj = < get_x : int > ;; введите simpler_obj = < get_x : int >
Объект x
не этого типа; но структурно x
относится к подтипу этого типа, поскольку x
содержит надмножество его методов. Так x
можно принуждать к этому типу:
# ( x :> simpler_obj ) ;; - : simpler_obj = < obj > # ( x :> simpler_obj ) # get_x ;; - : int = 10
Но не объект z
, потому что это не структурный подтип:
# (z:> simpler_obj) ;;Это выражение нельзя заставить ввести simpler_obj = <get_x: int>;он имеет тип <blahblah: float; set_x: int -> unit> но здесь используется с типом <get_x: int; ..>Первый тип объекта не имеет метода get_x
Это показывает, что совместимость для расширяющихся принуждений носит структурный характер.
Ссылки [ править ]
- ^ "Полиморфизм на основе подписи" .
- ^ Кук, WR; Hill, WL; Консервирование, PS (январь 1990 г.). «Наследование - это не подтип» . Материалы семнадцатого ежегодного симпозиума ACM по принципам языков программирования . Сан-Франциско, Калифорния: 125–135. DOI : 10.1145 / 96709.96721 . ISBN 978-0897913430.
- ^ «Типы объектов» .
- Пирс, Бенджамин С. (2002). «19,3». Типы и языки программирования . MIT Press. ISBN 978-0-262-16209-8.
Внешние ссылки [ править ]
- NominativeAndStructuralTyping в WikiWikiWeb