Как утка вводит отличающийся от старого 'различного' типа и/или интерфейсов?

43
задан Community 8 February 2017 в 14:09
поделиться

10 ответов

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

Утиному вводу можно подвести итог приятно как, "если он идет как утка, похож на утку, действует как утка, тогда это - утка". Это условия информатики полагает, что утка следующий интерфейс.

interface IDuck {
  void Quack();
}

Теперь позволяют нам исследовать Daffy

class Daffy {
  void Quack() {
    Console.WriteLine("Thatsssss dispicable!!!!");
  }
}

Daffy, не на самом деле IDuck в этом случае. Все же это действует точно так же, как Утка. Почему заставляют Daffy реализовать IDuck, когда довольно очевидно, что Daffy является на самом деле уткой.

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

IDuck d = new Daffy();
d.Quack();

к методу Шарлатана можно теперь обратиться "d" с полной безопасностью типов. Нет никакого шанса ошибки типа выполнения в этом присвоении или вызове метода.

19
ответ дан John Topley 26 November 2019 в 22:58
поделиться

Утиный ввод является просто другим термином для динамического контроля типов или позднего связывания. Различный объект, который анализирует/компилирует с любым членским доступом (например, obj. Что-либо), который может или не на самом деле быть определенным во время времени выполнения, утиный ввод.

5
ответ дан Mark Cidade 26 November 2019 в 22:58
поделиться

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

Так, прежде чем я дам свой ответ, я собираюсь предоставить несколько определений:

  1. Со строгим контролем типов

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

    Большинство языков имеет свойство "прогресса". Существуют многие, однако, которые не удовлетворяют свойство "сохранения". Хороший пример, C++ (и C также). Например, возможно в C++ принудить любой адрес памяти для поведения, как будто это был любой тип. Это в основном позволяет программистам нарушать систему типов любое время, которое они хотят. Вот простой пример:

    struct foo
    {
        int x;
        iny y;
        int z;
    }
    
    char * x = new char[100];
    foo * pFoo = (foo *)x;
    foo aRealFoo;
    *pFoo = aRealFoo;
    

    Этот код позволяет кому-то брать массив символов и писать экземпляр "нечто" в него. Если бы C++ был со строгим контролем типов, то это не было бы возможно. Безопасные с точки зрения типов языки, как C#, Java, VB, шепелявость, рубин, Python, и многие другие, выдали бы исключение, если бы Вы пытались бросить массив символов к экземпляру "нечто".

  2. Со слабым контролем типов

    Что-то со слабым контролем типов, если это не со строгим контролем типов.

  3. Со статическим контролем типов

    язык А со статическим контролем типов, если его система типов проверяется во время компиляции. Статически типизированный язык может быть или "со слабым контролем типов" как C или со строгим контролем типов как C#.

  4. С динамическим контролем типов

    динамически типизированный язык А является языком, где типы проверяются во времени выполнения. Много языков имеют смесь, какую-то, между статическим контролем типов и динамическим контролем типов. C#, например, проверит многие броски динамично во времени выполнения, потому что не возможно проверить их во время компиляции. Другими примерами являются языки как Java, VB и Objective C.

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

  5. Утка, вводящая

    , Утиный ввод - что-то, что абсолютно ортогонально к статическому, динамическому, слабому, или строгому контролю типов. Это - практика записи кода, который будет работать с объектом независимо от его базовых идентификационных данных типа. Например, следующий код VB.NET:

    function Foo(x as object) as object
        return x.Quack()
    end function
    

    будет работать, независимо от того, что тип объекта, это передается в "Нечто", при условии, что, определяет метод под названием "Шарлатан". Таким образом, если объект похож на утку, идет как утка и говорит как утка, то это - утка. Утиный ввод происходит во многие формы. Возможно иметь статический утиный ввод, динамический утиный ввод, сильный утиный ввод и недельный утиный ввод. Шаблонные функции C++ являются хорошим примером "слабого статического утиного ввода". Шоу в качестве примера в сообщении "JaredPar" показывает пример "сильного статического утиного ввода". Позднее связывание в VB (или код в Ruby или Python) включает "сильный динамический утиный ввод".

  6. Вариант

    вариант А является структурой данных с динамическим контролем типов, которая может содержать диапазон предопределенных типов данных, включая строки, целые типы, даты и объекты com. Это тогда определяет набор операций для присвоения, преобразования и управления данными, хранившими в вариантах. Со строгим контролем типов ли вариант, зависит от языка, на котором он используется. Например, вариант в программе VB 6 со строгим контролем типов. Время выполнения VB гарантирует, что операции, записанные в коде VB, будут соответствовать правилам ввода для вариантов. Связь для добавления строки к IUnknown через вариант вводит VB, приведет к ошибке периода выполнения. В C++, однако, варианты со слабым контролем типов, потому что все типы C++ со слабым контролем типов.

хорошо.... теперь, когда я избавился от определений, я могу теперь ответить на Ваш вопрос:

вариант А, в VB 6, включает одну форму выполнения утиного ввода. Существуют лучшие способы сделать утиный ввод (примером Jared Par является один из лучших), чем варианты, но можно сделать утиный ввод с вариантами. Таким образом, можно записать одну часть кода, который будет воздействовать на объект независимо от его базовых идентификационных данных типа.

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

31
ответ дан Tim Rutter 26 November 2019 в 22:58
поделиться

Вероятно, ничто не требует ввод утки, но это может быть удобно в определенных ситуациях. Скажите, что у Вас есть метод, который берет и использует объект Утки запечатанного класса из некоторой сторонней библиотеки. И Вы хотите сделать метод тестируемым. И у Утки есть ужасно большой API (отчасти как ServletRequest), о которых только необходимо заботиться о маленьком подмножестве. Как Вы тестируете его?

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

4
ответ дан Germán 26 November 2019 в 22:58
поделиться

Попытайтесь читать самый первый абзац статьи Wikipedia об утином вводе.
Утиный ввод на Википедию

у меня может быть интерфейс (IRunnable), который определяет Выполнение метода ().
, Если у меня есть другой класс с методом как это:
общественность освобождают RunSomeRunnable (IRunnable rn) {...}

У утки вводят дружественный язык, который я мог передать в любом классе, который имел Выполнение () метод в RunSomeRunnable () метод.
На статически типизированном языке класс, передаваемый в RunSomeRunnable, должен явно реализовать интерфейс IRunnable.

, "Если это Выполнение () как утка"

вариант больше похоже на объект в.NET, по крайней мере.

3
ответ дан BuddyJoe 26 November 2019 в 22:58
поделиться

@Kent Fredric

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

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

public interface ICreature { }
public interface IFly { fly();}
public interface IWalk { walk(); }
public interface IQuack { quack(); }
// ETC

// Animal Class
public class Duck : ICreature, IWalk, IFly, IQuack
{
    fly() {};
    walk() {};
    quack() {};
}

public class Rhino: ICreature, IWalk
{
    walk();
}

// In the method
List<ICreature> creatures = new List<ICreature>();
creatures.Add(new Duck());
creatures.Add(new Rhino());   

foreach (ICreature creature in creatures)
{
    if (creature is IFly)        
         (creature as IFly).fly();        
    if (creature is IWalk) 
         (creature as IWalk).walk();         
}
// Etc
2
ответ дан FlySwat 26 November 2019 в 22:58
поделиться

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

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

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

Для ответа на Вас более непосредственно:

... поэтому снова я просто не получаю его. Действительно ли это - фантастическое средство экономии времени или та же старая вещь в совершенно новом мешке?

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

действительно ли это - панацея, которая сохранит все человечество от исчезновения? Нет. И любой, кто говорит Вам иначе, является зилотом.

2
ответ дан Jason Baker 26 November 2019 в 22:58
поделиться

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

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

Пример вариантов по сравнению с утиным вводом:

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

Используя варианты: Никакая удача. Я могу создать вариант, который может содержать объект UserFromDbRecord или объект UserFromLdap, но объекты UserFromLdap не будут применимы стандартными программами, которые ожидают объекты от иерархии FromDbRecord.

Используя утиный ввод: Я могу посещать свой урок UserFromLdap и добавить несколько методов, которые заставляют его действовать как класс UserFromDbRecord. Я не должен копировать весь интерфейс FromDbRecord, как раз для стандартных программ, которые я должен использовать. Если я делаю это правильно, это - чрезвычайно мощная и гибкая техника. Если я делаю это неправильно, это производит очень запутывающий и хрупкий код (подвергающийся поломке если или библиотека DB или изменения библиотеки LDAP).

1
ответ дан Josh Kelley 26 November 2019 в 22:58
поделиться

Я думаю, что базовая точка утиного ввода - то, как это используется. Каждый использует обнаружение метода и самоанализ объекта для знания, что сделать с ним, вместо того, чтобы объявить заранее, чем это будет быть (где Вы знаете, что сделать с ним).

Это, вероятно, более практично на языках OO, где примитивы не являются примитивами и являются вместо этого объектами.

я думаю лучший способ подвести итог его в различном типе, объект/может быть чем-либо, и что это, сомнительно, в противоположность объекту [только 112] взгляды как что-либо, но можно разработать то, что это путем выяснения у него.

Вот что-то, чему я не верю, вероятно без ducktyping.

sub dance { 
     my $creature = shift;
     if( $creature->can("walk") ){ 
         $creature->walk("left",1);
         $creature->walk("right",1); 
         $creature->walk("forward",1);
         $creature->walk("back",1);
     }
     if( $creature->can("fly") ){ 
          $creature->fly("up"); 
          $creature->fly("right",1); 
          $creature->fly("forward",1); 
          $creature->fly("left", 1 ); 
          $creature->fly("back", 1 ); 
          $creature->fly("down");
     } else if ( $creature->can("walk") ) { 
         $creature->walk("left",1);
         $creature->walk("right",1); 
         $creature->walk("forward",1);
         $creature->walk("back",1);
     } else if ( $creature->can("splash") ) { 
         $creature->splash( "up" ) for ( 0 .. 4 ); 
     }
     if( $creature->can("quack") ) { 
         $creature->quack();
     }
 }

 my @x = ();  
 push @x, new Rhinoceros ; 
 push @x, new Flamingo; 
 push @x, new Hyena; 
 push @x, new Dolphin; 
 push @x, new Duck;

 for my $creature (@x){

    new Thread(sub{ 
       dance( $creature ); 
    }); 
 }

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

И это действительно сосет с точки зрения просто попытки выполнить хорошую хореографию.

1
ответ дан John Topley 26 November 2019 в 22:58
поделиться

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

0
ответ дан 26 November 2019 в 22:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: