Что такое утка? - PullRequest
       63

Что такое утка?

363 голосов
/ 17 ноября 2010

Я наткнулся на термин утка, набрав , когда читал случайные темы о программном обеспечении в Интернете, и не совсем понял его.

Что такое «типирование утки»?

Ответы [ 12 ]

273 голосов
/ 17 ноября 2010

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

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

Название происходит от фразы «Если он выглядит как утка и крякает как утка, это утка».

Википедия содержит гораздо больше информации.

178 голосов
/ 17 ноября 2010

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

В отличие от того, что говорили другие, это не обязательно относится к динамическим языкам или проблемам наследования.

Пример задачи: Вызов какого-либо метода Quack для объекта.

Без , использующего типизацию утки, функция f, выполняющая эту задачу, должна заранее указать, что ее аргумент должен поддерживать некоторый метод Quack.Распространенным способом является использование интерфейсов

interface IQuack { 
    void Quack();
}

void f(IQuack x) { 
    x.Quack(); 
}

Вызов f(42) завершается неудачно, но f(donald) работает, пока donald является экземпляром IQuack -подтипа.

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

def f(x : { def Quack() : Unit }) = x.Quack() 

Мы могли бы даже написать

f :: Quackable a => a -> IO ()
f = quack

в Хаскеле, где класс типов Quackable обеспечивает существование нашего метода.


Так как же утка печатает изменить это?

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

Таким образом, система динамических типов, как в Python, всегда использует уткунабрав:

def f(x):
    x.Quack()

Если f получит x с поддержкой Quack(), все в порядке, если нет, то произойдет сбой во время выполнения.

Но утка не набираетЭто вообще подразумевает динамическую типизацию - на самом деле, существует очень популярный, но полностью статический подход к типу утиной типизации, который тоже не предъявляет никаких требований:

template <typename T>
void f(T x) { x.Quack(); } 

Функция никоим образом не сообщает, что онахочет некоторый x, который может Quack, поэтому вместо этого он просто пытается во время компиляции , и если все работает, все в порядке.

95 голосов
/ 05 ноября 2016

Простое объяснение (без кода)

Обсуждение семантики вопроса довольно нюансировано (и очень академично), но вот общая идея:

Duck Typing

(«Если он ходит как утка и крякает как утка, значит, это утка».) - ДА!но что это значит ??! Это лучше всего иллюстрируется на примере:

Пример: языки с динамической типизацией

Представьте, что у меня есть волшебная палочка.У него есть особые полномочия.Если я взмахну палочкой и скажу «Езжай!» машине, то тогда она едет!

Работает ли она на других вещах?Не уверен: поэтому я пробую это на грузовике.Ух ты - это тоже диски!Затем я пробую это на самолетах, поездах и 1 Вудсе (это тип гольф-клуба, который люди используют, чтобы «водить» мяч для гольфа). Они все ездят!

Но сработает ли, скажем, чашка?Ошибка: KAAAA-BOOOOOOM!это не сработало так хорошо.====> Чашки не могут водить!Дух!?

Это в основном концепция печатания утки.Это система "попробуй, прежде чем купить" .Если это работает, все хорошо.Но если это не удастся, ну, это взорвется вам в лицо.

Другими словами, нас интересует, что объект может делать , а не с , как этот объектis .

Пример: языки со статической типизацией

Если нас интересует , каким на самом деле был объект , тогда наш магический трюкработают только на заранее заданных, авторизованных типах - в этом случае автомобили, но будут выходить из строя на других объектах, которые могут ездить : грузовиках, мопедах, тук-туках и т. д. Это не будет работать на грузовиках, потому что наша магияпалочка ожидает, что она будет работать только на автомобилях .

Другими словами, в этом сценарии волшебная палочка очень внимательно смотрит на то, что объект является (это автомобиль?), А не на то, что объект может сделать (например, могут ли автомобили, грузовики и т. д.).

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

Краткое описание: Выдача ключа

Что важно при наборе утки, так это объектможет на самом деле делать, , а не то, что объект является .

22 голосов
/ 10 ноября 2015

Предположим, вы разрабатываете простую функцию, которая получает объект типа Bird и вызывает его метод walk(). Есть два подхода, о которых вы можете подумать:

  1. Это моя функция, и я должен быть уверен, что она принимает только Bird, иначе их код не скомпилируется. Если кто-то хочет использовать мою функцию, он должен знать, что я принимаю только Bird s
  2. Моя функция получает любой objects, и я просто вызываю метод walk() объекта. Таким образом, если object может walk(), это правильно, если не может, моя функция не будет работать. Поэтому здесь не важно, является ли объект Bird или чем-то еще, важно, что он может walk() (это утка, набирающая )

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


Полезное чтение

16 голосов
/ 17 ноября 2010

В Википедии есть довольно подробное объяснение:

http://en.wikipedia.org/wiki/Duck_typing

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

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

6 голосов
/ 17 января 2019

Я вижу много ответов, которые повторяют старую идиому:

Если это похоже на утку и крякает как утка, то это утка

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

Я не нахожу особой помощи.

Это лучшая попыткаНа простом английском ответе о наборе утки, который я нашел:

Утиная печать означает, что объект определяется тем, что он может делать, а не тем, чем он является.

Это означает, что мы меньше заботимся о классе / типе объекта и больше заботимся о том, какие методы могут быть вызваны для него и какие операции могут быть выполнены с ним. Мы не заботимся о его типе, мы заботимся о том, что он может сделать .

2 голосов
/ 09 августа 2018

обход дерева с техникой печати утки

def traverse(t):
    try:
        t.label()
    except AttributeError:
        print(t, end=" ")
    else:
        # Now we know that t.node is defined
        print('(', t.label(), end=" ")
        for child in t:
            traverse(child)
        print(')', end=" ")
2 голосов
/ 30 сентября 2017

Duck Typing - это не подсказка типа!

В основном, чтобы использовать "duck Typing", вы не будете нацеливаться на конкретный тип, а скорее на более широкий диапазон подтипов (не говоря о наследовании, когда я имею в виду подтипы Iозначает «вещи», которые вписываются в один и тот же профиль), используя общий интерфейс.

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

Типы хранилища могут быть: файл, база данных, сеанс и т. Д.

Интерфейс позволит вам узнать о доступных опциях(методы) независимо от типа хранилища, что означает, что на данный момент ничего не реализовано!Другими словами, Интерфейс не знает ничего о том, как хранить информацию.

Каждая система хранения должна знать о существовании интерфейса, применяя те же самые методы.

interface StorageInterface
{
   public function write(string $key, array $value): bool;
   public function read(string $key): array;
}


class File implements StorageInterface
{
    public function read(string $key): array {
        //reading from a file
    }

    public function write(string $key, array $value): bool {
         //writing in a file implementation
    }
}


class Session implements StorageInterface
{
    public function read(string $key): array {
        //reading from a session
    }

    public function write(string $key, array $value): bool {
         //writing in a session implementation
    }
}


class Storage implements StorageInterface
{
    private $_storage = null;

    function __construct(StorageInterface $storage) {
        $this->_storage = $storage;
    }

    public function read(string $key): array {
        return $this->_storage->read($key);
    }

    public function write(string $key, array $value): bool {
        return ($this->_storage->write($key, $value)) ? true : false;
    }
}

Так что теперь, каждый раз, когда вам нужно записать / прочитать информацию:

$file = new Storage(new File());
$file->write('filename', ['information'] );
echo $file->read('filename');

$session = new Storage(new Session());
$session->write('filename', ['information'] );
echo $session->read('filename');

В этом примере вы в конечном итоге будете использовать конструктор Duck Typing in Storage:

function __construct(StorageInterface $storage) ...

Надеюсь, это помогло;)

2 голосов
/ 15 июня 2017

Глядя на сам язык, может помочь; это часто помогает мне (я не являюсь носителем английского языка).

В duck typing:

1) слово typing не означает печатать на клавиатуре (как это было в моем представлении), оно означает определение " что это за вещь? * 2) слово duck выражает, как осуществляется это определение; это своего рода «свободное» определение, например: « если он ходит как утка ... тогда это утка ». Это «свободно», потому что вещь может быть уткой или нет, но не имеет значения, действительно ли это утка; важно то, что я могу делать с этим то же самое, что я могу делать с утками и ожидать поведения, которое демонстрируют утки. Я могу накормить его хлебными крошками, и вещь может пойти ко мне, или напасть на меня, или отступить ... но это не поглотит меня, как гризли.

2 голосов
/ 07 ноября 2016

Утка набрав:

Если он говорит и ходит как утка, значит, это утка

Это обычно называется похищением ( похищением рассуждением или также называется повторением , более ясное определение, я думаю):

  • из C (вывод , что мы видим ) и R (правило , что мы знаем ), мы принять / решить / принять P (предпосылка, свойство ), другими словами, данный факт

    ... сама основа медицинского диагноза

    с утками: C = прогулки, разговоры , R = как утка , P = это утка

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

  • объект o имеет метод / свойство mp1 и интерфейс / тип T требует / определяет mp1

  • объект o имеет метод / свойство mp2 и интерфейс / тип T требует / определяет mp2

  • ...

Итак, более чем просто принять mp1 ... для любого объекта, если он соответствует определению mp1 ..., компилятор / среда выполнения также должны быть в порядке с утверждение o относится к типу T

И хорошо, это так с примерами выше? Утиная печать, по сути, вообще не печатает? Или мы должны назвать это неявной типизацией?

...