Система структурного типа - Structural type system - Wikipedia

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

Описание

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

Например, OCaml использует структурную типизацию методов для совместимости типов объектов. Идти использует структурную типизацию методов для определения совместимости типа с интерфейсом. Шаблон C ++ функции демонстрируют структурную типизацию аргументов типа. Haxe использует структурную типизацию, но у классов нет структурных подтипов.

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

Существует различие между структурной заменой предполагаемого и не предполагаемого полиморфизма. Некоторые языки, например Haskell, не заменяйте структурно в случае, когда ожидаемый тип объявлен (т. е. не выведен), например, заменяйте только функции, которые являются полиморфными на основе сигнатур посредством вывода типа.[1] Тогда невозможно случайно подтипировать невыведенный тип, хотя все еще может быть возможно обеспечить явное преобразование в невыведенный тип, который вызывается неявно.

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

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

В 1990 году Кук и др. Доказали, что наследование не подтип на структурно-типизированных ОО-языках.[2]

Пример

Объекты в OCaml структурно типизированы по именам и типам их методов.

Объекты можно создавать напрямую (непосредственные объекты) без именительного класса. Классы служат только как функции для создания объектов.

 # позволять Икс =     объект       вал изменчивый Икс = 5       метод get_x = Икс       метод set_x у = Икс <- у     конец;; вал Икс : < get_x : int; set_x : int -> единица измерения > = <объект>

Здесь интерактивная среда выполнения OCaml для удобства распечатывает предполагаемый тип объекта. Его тип (< get_x : int; set_x : int -> unit >) определяется только его методами. Другими словами, тип x определяется типами методов «get_x: int» и «set_x: int -> unit», а не каким-либо именем.[3]

Чтобы определить другой объект, который имеет те же методы и типы методов:

 # позволять у =     объект       метод get_x = 2       метод set_x у = Printf.printf "% d п" у     конец;; вал у : < get_x : int; set_x : int -> единица измерения > = <объект>

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

 # Икс = у;; - : bool = ложный

Значит, они должны быть одного типа, иначе это даже не проверка типа. Это показывает, что эквивалентность типов структурна.

Можно определить функцию, которая вызывает метод:

 # позволять set_to_10 а = а#set_x 10;; вал set_to_10 : < set_x : int -> 'а; .. > -> 'а = <весело>

Выведенный тип для первого аргумента (< set_x : int -> 'a; .. >) Интересно. В .. означает, что первым аргументом может быть любой объект, у которого есть метод "set_x", который принимает в качестве аргумента int.

Так что его можно использовать на объекте Икс:

 # set_to_10 Икс;; - : единица измерения = ()

Можно создать другой объект, который имеет этот метод и тип метода; остальные методы не имеют значения:

 # позволять z =     объект       метод бла-бла = 2.5       метод set_x у = Printf.printf "% d п" у     конец;; вал z : < бла-бла : плавать; set_x : int -> единица измерения > = <объект>

С ним также работает функция "set_to_10":

 # set_to_10 z;; 10 - : единица измерения = ()

Это показывает, что совместимость таких вещей, как вызов метода, определяется структурой.

Давайте определим синоним типа для объектов только с помощью метода get_x и без других методов:

 # тип simpler_obj = < get_x : int >;; тип simpler_obj = < get_x : int >

Предмет Икс не относится к этому типу; но конструктивно Икс принадлежит к подтипу этого типа, поскольку Икс содержит расширенный набор его методов. Так Икс может быть принужден к этому типу:

 # (Икс :> simpler_obj);; - : simpler_obj = <объект> # (Икс :> simpler_obj)#get_x;; - : int = 10

Но не возражаю z, потому что это не структурный подтип:

# (z:> simpler_obj) ;; Это выражение нельзя принудить к типу simpler_obj = ; оно имеет тип  unit>, но здесь используется с типом  Первый тип объекта не имеет метода get_x

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

Рекомендации

  1. ^ «Сигнатурный полиморфизм».
  2. ^ Cook, W.R .; Hill, W.L .; Консервирование, П.С. (Январь 1990 г.). «Наследование - это не подтип». Материалы семнадцатого ежегодного симпозиума ACM по принципам языков программирования. Сан-Франциско, Калифорния: 125–135. Дои:10.1145/96709.96721. ISBN  978-0897913430.
  3. ^ «Типы объектов».

внешняя ссылка