Java使实现类明确声明其实现的接口的设计选择就是设计选择。可以肯定的是,JVM已经针对此选择进行了优化,并且除非添加了一些新的JVM指令,否则 现在
可能要付出额外的代价来实现另一个选择(例如Scala的结构化类型)。
那么设计选择到底 是 什么呢?一切都归结为方法的语义。考虑:以下方法在语义上是否相同?
- draw(String graphicShapeName)
- draw(String handgunName)
- draw(String playingCardName)
这三种方法都具有签名
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:程序员必须明确声明他的意图,然后机器会对其进行检查。假设程序员可能会犯语义错误(图形/手枪/卡)。
继续:程序员必须声明其意图的至少一部分,但是检查机器时机器可以继续运行。假设程序员可能会犯一个笔误(整数/字符串),而不会犯语义上的错误(图形/手枪/卡)。
鸭式打字:程序员无需表达任何意图,机器无需检查。假定程序员不太可能犯文书或语义错误。
解决接口和一般键入是否足以测试笔误和语义错误超出了此答案的范围。完整的讨论将不得不考虑构建时编译器技术,自动化测试方法,运行时/热点编译以及许多其他问题。
公认的
draw(String)是,故意夸大示例以说明问题。实际示例将涉及更丰富的类型,这些类型将提供更多线索来消除方法的歧义。



