Утка набирает, она должна быть динамичной? - PullRequest
24 голосов
/ 22 декабря 2009

Википедия говорила * о наборе утки :

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

(* Примечание редактора: поскольку этот вопрос был опубликован, статья в Википедии была отредактирована для удаления слова "динамический".)

В нем говорится о структурном наборе :

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

Это контрастирует структурное подтипирование с типизацией утки следующим образом:

[Структурные системы] контрастирует с ... утка печатает, в которой только часть структуры доступна на время выполнения проверяется на совместимость.

Однако термин типизирование утки , по-моему, по крайней мере интуитивно относится к структурным системам подтипирования. На самом деле Википедия говорит:

Название концепции [утка-печатка] относится к тесту утка , приписывается Джеймс Уиткомб Райли, который можно сформулировать как следует: «когда я вижу птицу, которая ходит как утка и плавает как утка и крякает как утка, я называю эту птицу уткой ".

Итак, мой вопрос: почему я не могу назвать структурный подтип типизацией утки? Существуют ли даже динамически типизированные языки, которые также нельзя классифицировать как типизированные по типу утки?

Постскриптум:

Как кто-то по имени daydreamdrunk на reddit.com, так что красноречиво выразил это"Если он компилируется как утка и ссылки как утка ..."

Post-приписка

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

Ответы [ 8 ]

26 голосов
/ 22 декабря 2009

Шаблоны C ++ и D являются отличным примером неинтегральной типизации. Это определенно:

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

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

13 голосов
/ 22 декабря 2009

Структурная система типов

Система структурных типов сравнивает один целый тип с другим целым типом, чтобы определить, совместимы ли они. Для совместимости двух типов A и B A и B должны иметь одинаковую структуру, то есть каждый метод для A и B должен иметь та же подпись.

Duck Typing

Утиная типизация считает два типа эквивалентными для выполняемой задачи , если они оба могут справиться с этой задачей. Чтобы два типа A и B были эквивалентны фрагменту кода, который хочет записать в файл, A и B оба должны реализовать метод записи.

Резюме

Структурные системы типов сравнивают каждую сигнатуру метода (всю структуру). Утиная типизация сравнивает методы, относящиеся к конкретной задаче (структура, относящаяся к задаче).

10 голосов
/ 22 декабря 2009

Утиная печать означает Если она просто подходит, все в порядке

Это относится как к динамически набираемым

def foo obj
    obj.quak()
end

или статически типизированные, скомпилированные языки

template <typename T>
void foo(T& obj) {
    obj.quak();
}

Дело в том, что в обоих примерах не было никакой информации о данном типе. Просто при использовании (во время выполнения или во время компиляции!) Типы проверяются, и если все требования выполнены, код работает. Значения не имеют явного типа в точке их объявления.

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

Структурно типизированный код (в стиле Scala) для приведенного выше примера будет

def foo(obj : { def quak() : Unit }) {
    obj.quak()
}

Не путайте это с тем фактом, что некоторые структурно типизированные языки, такие как OCaml, сочетают это с выводом типов, чтобы помешать нам явно определять типы.

6 голосов
/ 22 декабря 2009

Я не уверен, что это действительно отвечает на ваш вопрос, но ...

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

template<typename T>
struct Test
{
    void op(T& t)
    {
        t.set(t.get() + t.alpha() - t.omega(t, t.inverse()));
    }
};
5 голосов
/ 22 декабря 2009

Всегда будут примеры из некоторых языков программирования, которые нарушают некоторые определения различных терминов. Например, ActionScript поддерживает программирование в стиле утиной печати на экземплярах, которые не являются технически динамическими.

var x:Object = new SomeClass();
if ("begin" in x) {
    x.begin();
}

В этом случае мы проверяли, есть ли у экземпляра объекта в «x» метод «begin» перед его вызовом вместо использования интерфейса. Это работает в ActionScript и в значительной степени напоминает утку, хотя сам класс SomeClass () может не быть динамическим.

5 голосов
/ 22 декабря 2009

Насколько я понимаю, структурная типизация используется механизмами определения типов и тому подобным для определения информации о типах (например, Haskell или OCaml), в то время как типизация утки не заботится о «типах» как таковых, просто эта вещь может обрабатывать определенные вызов метода / доступ к свойству и т. д. (например, respond_to? в Ruby или проверка возможностей в Javascript).

4 голосов
/ 17 апреля 2014

Существуют ситуации, в которых динамическая типизация утки и аналогичный код статической типизации (например, C ++) ведут себя по-разному:

template <typename T>
void foo(T& obj) {
    if(obj.isAlive()) {
        obj.quak();
    }
}

В C ++ объект должен иметь как isAlive, так и quak методы для компиляции кода; для эквивалентного кода в динамически типизированных языках объект должен иметь метод quak, только если isAlive() возвращает true. Я интерпретирую это как разницу между структурой (структурная типизация) и поведением (утиная типизация).

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

2 голосов
/ 24 апреля 2014

Я вижу «типизацию утки» скорее как стиль программирования, тогда как «структурная типизация» - это особенность системы типов.

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

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

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

Так что, хотя я могу видеть, как есть общий язык, я не думаю, что типирование утки относится к структурному типированию. Как я думаю о них, типизация утки - это даже не та вещь, которая могла бы включать структурную типизацию, потому что это не одно и то же. Думая о том, что утилитная типизация в динамических языках просто «неявные, непроверенные структурные типы» чего-то не хватает, ИМХО. Duck typing - это стиль кодирования, который вы выбираете или не используете, а не просто техническая особенность языка программирования.

Например, можно использовать isinstance проверки в Python для имитации ограничений типа "класс или подкласс" в стиле OO. Также можно проверить наличие определенных атрибутов и методов, чтобы имитировать ограничения структурного типа (вы даже можете поместить проверки во внешнюю функцию, таким образом, эффективно получая именованный структурный тип!). Я бы сказал, что ни один из этих вариантов не является примером типизации утки (если только структурные типы не очень хорошо детализированы и не синхронизированы с проверкой кода).

...