Некоторое время я искал в SO, и не смог найти однозначного и общего ответа, только некоторые противоречивые и особые мнения. [1]
Итак, я хотел бы знать, какова связь между типизацией утки и общим программированием? (DT < GP, DT == GP, DT> GP). Под общим программированием я имею в виду, в частности, шаблоны C ++ или общие шаблоны Java, но будет приветствоваться общий ответ, связанный с концепциями, если это возможно.
Я знаю, что общее программирование будет обрабатываться во время компиляции, в то время как типизация утки будет обрабатываться во время выполнения, но кроме этого, я не знаю, как их позиционировать.
Наконец, я не хочу начинать дебаты, поэтому я бы предпочел ответы, такие как причины, причины против.
[1] Какая связь между шаблоном C ++ и типизацией утки?Я сталкивался с двумя различными определениями «Утиной печати». Несомненно, есть люди, которые скажут вам, что один из них «правильный», а другой «неправильный». Я просто пытаюсь задокументировать, что они оба используются, а не сказать, что они оба «правильные», но лично я не вижу ничего плохого в более широком значении.
1) время выполнения только для набора текста. Тип — это свойство объектов, а не переменных, и, следовательно, обязательно когда вы вызываете метод для объекта или иным образом используете свойства, которые он имеет в силу своего типа, присутствие или отсутствие этого метода обнаруживается во время выполнения [*]. Так что, если он «выглядит как утка и крякает как утка» (то есть, если оказывается quack()
функция), то это «утка» (во всяком случае, вы можете относиться к нему как к одному). По этому определению конечно шаблоны С ++ попадают на первое препятствие, они используют статическую типизацию.
2) Имя, используемое более широко для принцип что если он выглядит как утка и крякает как утка, то это утка, то есть любая настройка, в которой интерфейсы косвенным образом определяется операциями, выполняемыми потребителем интерфейса, а не интерфейсами, которые явно объявляются производителем (независимо от того, что реализует интерфейс). Согласно этому определению, шаблоны C ++ действительно используют своего рода типизацию утки, но определяется ли что-то «как утка» во время компиляции, а не во время выполнения, основываясь на его статическом типе, а не на его динамическом типе. «Проверять во время компиляции, может ли статическая переменная типа этой переменной крякать?», А не «проверять во время выполнения, может ли этот объект крякать?».
Мне кажется, что спор, по сути, заключается в том, «владеет» ли Python термином, так что только Python-подобные системы типов могут быть названы утиной типизацией, или же другие могут свободно использовать термин для обозначения аналогичной концепции в другом контексте. , Независимо от того, что вы думаете, это должно означать, кажется безответственно использовать термин «шутка» и требовать, чтобы все понимали одно и то же формальное определение из него. SO не является подходящим форумом, чтобы рассказать вам, что означает термин «должен», если только нет авторитетного источника, о котором вы спрашиваете, например словарь или какие-либо научные статьи, которые определяют его формально. Я думаю, что он может сказать вам, что он на самом деле имел в виду.
«Общее программирование» может использовать утку или нет, в зависимости от точных деталей. Универсальные контейнеры C ++ действительно используют типизацию типа «тип 2», потому что для общего типа в C ++ не гарантируется, что вы можете скопировать его, сравнить его, получить значение хеш-функции и т. Д. Универсальные контейнеры Java этого не делают, Object
уже достаточно методов, чтобы сделать его хэш
И наоборот, я подозреваю, что все, что вы делаете, использует утки, может быть разумно упомянуто как «общее программирование». Итак, я полагаю, что в терминах, которые вы просили, GP> DT в этой типизации утки (любое определение) является строгим подмножеством из широкого спектра вещей, которые можно назвать «общими».
[*] хорошо, в некоторых случаях ваш динамический язык может иметь некоторый статический анализ, который так или иначе доказывает случай, но язык требует способности отложить эту проверку до времени выполнения для случаев, когда статический анализ не может окончательно сказать.Это действительно вопрос лексики. В самом общем смысле,
универсальное программирование не связано с проблемой времени компиляции
время выполнения: это решение общей проблемы. Хороший пример
где общее программирование — это Python, но это также возможно
реализовать универсальное программирование во время выполнения на C ++ (со значительными затратами
во время исполнения).
Типирование утки является ортогональным понятием и обычно используется, чтобы подразумевать
время выполнения. Опять же, наиболее часто цитируемый современный пример
Python, но многие, многие языки, начиная с Lisp, использовали его в
прошлое. Как правило, и C ++, и Java сделали явное
выбор не поддержать утку набрав. Это компромисс: безопасность против
гибкость (или ошибки во время компиляции против ошибок во время выполнения).
Java не поддерживает утку на языке. Он поддерживает рефлексию, которая может достичь того же. Насколько я вижу, он не имеет никакого отношения к Generics в Java, на самом деле заставить их работать вместе — настоящая боль.
Для меня «типизирование утки» означает, что нет никаких явных отношений соответствия. Если что-то ходит, как утка, и говорит, как утка, к нему можно относиться как к утке, и не нужно явно объявлять, что это утка. В терминах C ++ ему не нужно наследовать от базового класса Duck: наследование — это способ явно объявить, что один класс соответствует интерфейсу другого.
Это понятие ортогонально тому, происходит ли проверка типов во время выполнения или во время компиляции. Такие языки, как Smalltalk, обеспечивают типизацию утки, которая происходит во время выполнения (и наследование используется для повторного использования реализации, а не для объявления соответствия интерфейса). Шаблоны C ++ — это форма утки, которая происходит во время компиляции.
И это последнее предложение является ответом на вопрос.