鸭子类型在软件开发中意味着什么?


当前回答

“鸭子打字”这个词是一个谎言。

“走路像鸭子,叫起来像鸭子,那就是鸭子”这句俗语在这里一次又一次地被重复着。

但这并不是鸭子打字(或者我们通常所说的鸭子打字)的意思。所有我们正在讨论的鸭子打字,是试图强制命令的东西。看看有什么东西是不是嘎嘎叫,不管它说什么。但是并没有推论出这个物体是不是鸭子。

For true duck typing, see type classes. Now that follows the idiom “If it walks like a duck and quacks like a duck then it is a duck.". With type classes, if a type implements all the methods that are defined by a type class, it can be considered a member of that type class (without having to inherit the type class). So, if there is a type class Duck which defines certain methods (quack and walk-like-duck), anything that implements those same methods can be considered a Duck (without needing to inherit Duck).

其他回答

它是一个用于没有强类型的动态语言中的术语。

其思想是,为了调用对象上的现有方法,您不需要指定类型——如果在对象上定义了方法,则可以调用它。

这个名字来源于一句话“如果它看起来像鸭子,叫起来像鸭子,那它就是鸭子”。

维基百科有更多的信息。

维基百科有相当详细的解释:

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

鸭子打字是一种动态的风格 输入一个对象的电流 方法和属性集 而是确定有效的语义 比它从一个特定的继承 类的实现 接口。

重要的是,使用duck类型时,开发人员可能更关心被使用的对象部分,而不是实际的底层类型是什么。

看看语言本身可能会有所帮助;它经常帮助我(我的母语不是英语)。

在鸭子打字中:

1)打字这个词并不是指在键盘上打字(就像我脑海中一直存在的形象那样),而是指确定“那是什么类型的东西?”

2) duck这个词表示决定是如何完成的;这是一种“松散的”定语,比如:“如果它像鸭子一样走路……那它就是一只鸭子。”之所以说“松散”,是因为这个东西可能是一只鸭子,也可能不是,但它是否真的是一只鸭子并不重要;重要的是我能像对待鸭子一样对待它,期待鸭子表现出的行为。我可以喂它面包屑,它可能会向我扑来,向我冲来,或者后退……但它不会像灰熊那样把我吃掉。

Duck Typing:

let anAnimal 

if (some condition) 
  anAnimal = getHorse()
else
  anAnimal = getDog()

anAnimal.walk()

上述函数调用在结构类型中无效

以下将适用于结构类型:

IAnimal anAnimal

if (some condition) 
      anAnimal = getHorse()
    else
      anAnimal = getDog()
    
anAnimal.walk()

这就是所有的,我们中的许多人已经直观地知道鸭子打字。

Duck typing 意味着一个操作没有正式指定其操作数必须满足的要求,而只是使用给定的条件进行尝试。

与其他人所说的不同,这并不一定与动态语言或继承问题有关。

示例任务:在对象上调用某个方法Quack。

如果不使用duck-typing,执行此任务的函数f必须事先指定其参数必须支持某种方法Quack。常用的方法是使用接口

interface IQuack { 
    void Quack();
}

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

调用f(42)失败,但f(donald)工作,只要donald是一个iquack子类型的实例。

另一种方法是结构类型—但同样,方法Quack()是正式指定的,任何不能提前证明它是嘎嘎作响的东西都会导致编译器失败。

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

我们甚至可以写成

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

在Haskell中,Quackable类型类确保了方法的存在。


So how does **duck typing** change this?

好吧,正如我所说的,duck输入系统不指定需求,而只是尝试任何可行的方法。

因此,像Python这样的动态类型系统总是使用duck类型:

def f(x):
    x.Quack()

如果f得到一个支持Quack()的x,一切正常,否则,它将在运行时崩溃。

但是鸭子类型并不意味着动态类型——事实上,有一种非常流行但完全静态的鸭子类型方法,它也没有给出任何要求:

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

该函数没有以任何方式告诉它想要某个可以Quack的x,所以它只是在编译时尝试,如果一切正常,就没问题。