我经常看到“鸭子打字”这个短语,甚至还遇到过一两个代码示例。我太懒忙于做自己的研究,有人可以简单地告诉我:
- “鸭子型”和老式“变体型”之间的区别,以及
- 提供一个示例,说明我可能更喜欢鸭子类型而不是变体类型,并且
- 提供一个我想要的例子have使用鸭子打字来完成?
我并不是想通过怀疑这个“新”结构的力量来显得愚蠢,我也不是通过拒绝进行研究来回避这个问题,但我对我所看到的所有蜂拥而至的炒作感到嘎嘎叫最近它。看起来像no对我来说打字(又名动态打字),所以我没有立即看到它的优点。
附录:感谢到目前为止提供的示例。在我看来,使用像“O->can(Blah)”这样的东西相当于进行反射查找(这可能并不便宜),和/或与编译器可能会说的(O是IBlah)大致相同能够为您检查,但后者的优点是可以区分我的 IBlah 界面和您的 IBlah 界面,而其他两个则不然。诚然,每个方法都有很多微小的接口会变得混乱,但同样可以检查很多单独的方法......
...所以我又不明白了。它是一个非常好的节省时间的工具,还是同样的旧东西装在一个全新的袋子里?哪里有这样的例子requires鸭子打字?
在此处的一些答案中,我看到了一些术语的错误使用,这导致人们提供错误的答案。
因此,在给出答案之前,我将提供一些定义:
-
强类型
如果一种语言强制执行程序的类型安全,则该语言是强类型的。这意味着它保证了两件事:一种叫做进步的东西,另一种叫做保存的东西。进步基本上意味着所有“有效类型”的程序实际上都可以由计算机运行,它们可能会崩溃,或抛出异常,或运行无限循环,但它们实际上可以运行。保留意味着如果一个程序是“有效类型的”,那么它将始终是“有效类型的”,并且没有变量(或内存位置)将包含不符合其指定类型的值。
大多数语言都具有“进度”属性。然而,有许多不满足“保存”属性。 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++ 是强类型的,这是不可能的。如果您尝试将字符数组转换为“foo”实例,类型安全语言(例如 C#、Java、VB、lisp、ruby、python 等)将引发异常。
-
弱类型
如果某些东西不是强类型的,那么它就是弱类型的。
-
静态类型
如果一种语言的类型系统在编译时得到验证,则该语言是静态类型的。静态类型语言可以是“弱类型”(如 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
无论传递到“Foo”的对象是什么类型,只要定义了一个名为“Quack”的方法,都可以工作。也就是说,如果该物体看起来像鸭子,走路像鸭子,说话像鸭子,那么它就是鸭子。鸭子打字有多种形式。可以有静态鸭子类型、动态鸭子类型、强鸭子类型和弱鸭子类型。 C++ 模板函数是“弱静态鸭子类型”的一个很好的例子。 “JaredPar”帖子中显示的示例显示了“强静态鸭子类型”的示例。 VB 中的后期绑定(或者 Ruby 或 Python 中的代码)可实现“强动态鸭子类型”。
-
Variant
变体是一种动态类型的数据结构,可以保存一系列预定义的数据类型,包括字符串、整数类型、日期和 com 对象。然后,它定义了一系列用于分配、转换和操作存储在变体中的数据的操作。变体是否是强类型取决于它所使用的语言。例如,VB 6 程序中的变体是强类型的。 VB 运行时确保用 VB 代码编写的操作符合变体的类型规则。通过 VB 中的变体类型将字符串添加到 IUnknown 将导致运行时错误。然而,在 C++ 中,变体是弱类型的,因为所有 C++ 类型都是弱类型的。
好的......现在我已经弄清楚了定义,我现在可以回答你的问题:
VB 6 中的一个变体支持一种形式的鸭子类型。与变体相比,有更好的方法进行鸭子类型(Jared Par 的示例是最好的示例之一),但您可以使用变体进行鸭子类型。也就是说,您可以编写一段代码来对对象进行操作,而不管其底层类型标识如何。
然而,使用变体来做这件事并不能真正提供很多验证。静态类型的鸭子类型机制(如 JaredPar 描述的那样)提供了鸭子类型的好处,以及编译器的一些额外验证。这真的很有帮助。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)