当前位置:  开发笔记 > 编程语言 > 正文

鸭子打字与旧的"变种"类型和/或界面有何不同?

如何解决《鸭子打字与旧的"变种"类型和/或界面有何不同?》经验,为你挑选了3个好方法。

我一直看到"鸭子打字"这个短语大肆渲染,甚至还遇到了一两个代码示例.我懒得忙着做自己的研究,有人可以简单地告诉我:

'duck type'和old-skool'变体类型'之间的区别,和

提供一个示例,我可能更喜欢鸭子打字而不是变种打字,以及

提供一个我必须使用duck typing来完成的事情的例子?

鸭子打字图由礼貌登记

通过怀疑这种"新"结构的力量,我不是故意要发怒的,而且我不会因为拒绝做研究而避开这个问题,但我正在喋喋不休地谈论我所看到的所有关于这个问题的大肆宣传.最近.它看起来像没有打字(也就是动态打字),所以我没有立即看到优势.

附录:感谢目前为止的例子.在我看来,使用类似'O-> can(Blah)'的东西相当于进行反射查找(可能并不便宜),和/或与编译器可能说的(O是IBlah)大致相同能够检查你,但后者的优点是区分我的IBlah界面和你的IBlah界面,而其他两个没有.当然,对于每种方法都有很多微小的接口会变得混乱,但是那样可以检查很多单独的方法......

...所以我再也没有得到它.在一个全新的麻袋中,它是一个梦幻般的节省时间,还是同样的老东西?需要鸭子打字的例子在哪里?



1> Scott Wisnie..:

在这里的一些答案中,我看到一些不正确的术语使用,导致人们提供错误的答案.

所以,在我给出答案之前,我将提供一些定义:

    强类型

    如果语言强制执行程序的类型安全,则强类型语言.这意味着它保证了两件事:称为进步和其他称为保存的东西.进度基本上意味着所有"有效类型"程序实际上可以由计算机运行,它们可能崩溃,或抛出异常,或运行无限循环,但它们实际上可以运行.保留意味着如果程序被"有效地键入",它将始终是"有效键入",并且没有变量(或内存位置)将包含不符合其指定类型的值.

    大多数语言都具有"进步"属性.然而,有许多不满足"保存"属性.一个很好的例子是C++(和C).例如,在C++中可以强制任何内存地址表现得像任何类型一样.这基本上允许程序员随时违反类型系统.这是一个简单的例子:

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

    此代码允许某人获取一个字符数组并为其编写"foo"实例.如果C++是强类型的,这是不可能的.类型安全的语言,如C#,Java,VB,lisp,ruby,python和许多其他语言,如果你试图将一个字符数组转换为"foo"实例,则会抛出异常.

    弱打字

    如果没有强类型,则输入的内容很弱.

    静态打字

    如果在编译时验证其类型系统,则静态类型化语言.静态类型语言可以像C一样"弱类型",也可以像C#一样强类型.

    动态输入

    动态类型语言是在运行时验证类型的语言.许多语言在静态和动态类型之间都有某种混合.例如,C#将在运行时动态验证多个强制转换,因为在编译时无法检查它们.其他示例是Java,VB和Objective-C等语言.

    还有一些语言是"完全"或"大部分"动态类型,如"lisp","ruby"和"small talk"

    鸭打字

    鸭子打字是与静态,动态,弱或强类型完全正交的东西.编写将与对象一起使用的代码的做法,无论其基础类型标识如何.例如,以下VB.NET代码:

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

    只要定义了一个名为"Quack"的方法,无论传递给"Foo"的对象类型是什么都可以工作.也就是说,如果物体看起来像鸭子,像鸭子一样走路,像鸭子一样说话,那就是鸭子.鸭子打字有多种形式.可以进行静态鸭子打字,动态鸭子打字,强鸭子打字和周鸭打字.C++模板函数是"弱静态鸭子打字"的一个很好的例子."JaredPar"帖子中的示例节目显示了"强静态鸭子打字"的示例.VB中的后期绑定(或Ruby或Python中的代码)实现了"强大的动态鸭子打字".

    变种

    变体是动态类型的数据结构,可以包含一系列预定义的数据类型,包括字符串,整数类型,日期和com对象.然后,它定义了一系列操作,用于分配,转换和操作变体中存储的数据.变量是否是强类型取决于它的使用语言.例如,VB 6程序中的变体是强类型的.VB运行时确保用VB代码编写的操作符合变体的输入规则.通过VB中的变体类型将字符串添加到IUnknown将导致运行时错误.但是,在C++中,变体是弱类型的,因为所有C++类型都是弱类型的.

好的....现在我已经把定义排除在外了,我现在可以回答你的问题了:

在VB 6中,一种变体可以实现鸭子打字的一种形式.有更好的方法做鸭子打字(Jared Par的例子是最好的),而不是变种,但你可以用变种做鸭子打字.也就是说,您可以编写一段代码来操作对象,而不管其基础类型标识.

但是,使用变体进行此操作并不能真正进行大量验证.一个静态类型的duck类型机制,就像JaredPar描述的那样,给出了duck typing的好处,以及编译器的一些额外验证.这真的很有帮助.


感谢扩展信息,但我很好奇一个声明:"如果没有强类型,那么每周都会输入一些内容." - 如果只是每周输入一次,那么不会每周输入一次吗?;-)
是的...我不是最好的拼写检查我的帖子.

2> JaredPar..:

简单的答案是变体是弱类型,而鸭子类型是强类型.

鸭子打字可以很好地总结为"如果它像鸭子一样走路,看起来像鸭子,像鸭子一样,那么它就像鸭子一样." 计算机科学术语认为鸭子是以下界面.

interface IDuck {
  void Quack();
}

现在让我们来看看Daffy

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

在这种情况下,Daffy实际上并不是IDuck.然而它就像鸭子一样.为什么让Daffy实施IDuck,因为很明显Daffy实际上是一只鸭子.

这就是Duck输入的地方.它允许在任何具有IDuck和IDuck引用的所有行为的类型之间进行类型安全转换.

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

Quack方法现在可以在"d"上调用,具有完整的类型安全性.此赋值或方法调用中不存在运行时类型错误的可能性.


@Otherside,你必须放弃接口是契约的想法.可悲的是,他们不是行为合同.它们只是数据传递合同.在明确实现接口的这方面,鸭子打字并不差.
关于Ducktyping我不明白的是:你怎么能确定Daffy的Quack方法等于IDuck.Quack?仅仅因为它具有相同的名称和参数类型匹配,并不一定意味着该方法可以满足您的需要....
这是鸭子打字的危险 - 没有语义检查,只有语法检查.但是,仅仅因为你在处理实现接口的类型时"更加确定",并不意味着你是"确定的".

3> Mark Cidade..:

鸭子打字只是动态打字或后期绑定的另一个术语.在运行时可能或不实际定义的任何成员访问(例如,obj.Anything)解析/编译的变体对象是鸭子类型.

推荐阅读
和谐啄木鸟
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有