Java 的设计选择是让实现类明确声明它们实现的接口,这就是一种设计选择。可以肯定的是,JVM 已针对此选择进行了优化,并且实现另一个选择(例如 Scala 的结构类型)可能会now除非添加一些新的 JVM 指令,否则会产生额外的成本。
那么究竟是什么is设计选择大约是?这一切都取决于方法的语义。考虑一下:以下方法在语义上是否相同?
- drawString 图形形状名称)
- 抽绳手枪名称)
- drawString 扑克牌名称)
所有三个方法都有签名draw(String)
。人们可能会从参数名称或通过阅读一些文档来推断它们具有不同的语义。有什么办法让机器知道它们是不同的吗?
Java 的设计选择是要求类的开发人员明确声明方法符合预定义接口的语义:
interface GraphicalDisplay {
...
void draw(String graphicalShapeName);
...
}
class JavascriptCanvas implements GraphicalDisplay {
...
public void draw(String shape);
...
}
毫无疑问,draw
中的方法JavascriptCanvas
旨在匹配draw
图形显示的方法。如果有人试图经过一个要拔出手枪的物体,机器就能检测到错误。
Go 的设计选择更加自由,允许事后定义接口。具体类不需要声明它实现的接口。相反,新纸牌游戏组件的设计者可以声明提供纸牌的对象必须具有与签名相匹配的方法draw(String)
。这样做的优点是可以使用具有该方法的任何现有类,而无需更改其源代码,但缺点是该类可能会拿出手枪而不是扑克牌。
鸭子类型语言的设计选择是完全放弃形式接口并简单地匹配方法签名。任何接口(或“协议”)的概念都是纯粹惯用的,没有直接的语言支持。
这些只是许多可能的设计选择中的三个。这三者可以简单地概括如下:
Java:程序员必须明确声明他的意图,机器会检查它。假设程序员可能会犯语义错误(图形/手枪/卡片)。
Go:程序员必须至少声明其意图的一部分,但机器在检查时几乎没有什么可继续进行的。假设程序员可能会犯错误(整数/字符串),但不太可能犯语义错误(图形/手枪/卡片)。
鸭子打字:程序员不需要表达任何意图,机器也不需要检查任何内容。假设程序员不太可能犯笔误或语义错误。
解决接口和一般类型是否足以测试书写和语义错误超出了本答案的范围。完整的讨论必须考虑构建时编译器技术、自动化测试方法、运行时/热点编译以及许多其他问题。
据了解,draw(String)
为了表达观点而故意夸大例子。真实的例子将涉及更丰富的类型,这将提供更多线索来消除方法的歧义。