为什么必须用Java声明接口?
|
有时,我们有几个类,这些类的某些方法具有相同的签名,但是与声明的Java接口不对应。例如,
JTextField
和JButton
(在ѭ2several中的其他几个)中都有一个方法
public void addActionListener(ActionListener l)
现在,假设我希望对具有该方法的对象进行操作;然后,我想有一个接口(或自己定义),例如
public interface CanAddActionListener {
public void addActionListener(ActionListener l);
}
这样我可以写:
public void myMethod(CanAddActionListener aaa, ActionListener li) {
aaa.addActionListener(li);
....
但是,可悲的是,我不能:
JButton button;
ActionListener li;
...
this.myMethod((CanAddActionListener)button,li);
此演员表将是非法的。编译器知道JButton
不是CanAddActionListener
,因为该类尚未声明实现该接口……但是,它“实际上”实现了该接口。
有时这很不方便-Java本身已经修改了几个核心类来实现由旧方法(例如,ѭ9)组成的新接口。
我的问题是:为什么会这样呢?我了解声明类实现接口的实用程序。但是无论如何,以我的示例为例,为什么编译器不能推断出类JButton
\“ satisfies \”接口声明(在其中查找)并接受强制转换?是编译器效率问题还是更多基本问题?
我对答案的总结:在这种情况下,Java可能允许某些“结构类型”(某种鸭子类型-但在编译时检查了)。没有。除了一些(对我来说尚不清楚)性能和实现方面的困难之外,这里还有一个更基本的概念:在Java中,接口(以及所有事物的声明)的声明并不仅仅意味着结构化(具有这些签名),但在语义上:方法应该实现某些特定的行为/意图。因此,在结构上满足某些接口的类(即,它具有带有所需签名的方法)不一定在语义上满足它(一个极端的示例:回想一下甚至没有方法的““ marker interfaces \”)。因此,Java可以断言一个类实现了一个接口,因为(并且仅因为)该接口已被明确声明。其他语言(Go,Scala)也有其他哲学。
没有找到相关结果
已邀请:
6 个回复
闪票仇门韧
毫无疑问,
中的
方法旨在与图形显示中的
方法匹配。如果有人试图通过将要拔出手枪的物体,则机器可以检测到错误。 Go \的设计选择更为自由,并允许在事实之后定义接口。具体的类无需声明其实现的接口。而是,新纸牌游戏组件的设计者可以声明提供纸牌的对象必须具有与签名“ 11”匹配的方法。这样做的好处是,可以使用具有该方法的任何现有类,而无需更改其源代码,但是缺点是该类可能会拔出手枪而不是纸牌。 鸭式语言的设计选择是完全放弃形式化接口,并简单地匹配方法签名。接口的任何概念(或“协议”)都是纯惯用语,没有直接的语言支持。 这些只是许多可能的设计选择中的三个。这三个可以概括如下: Java:程序员必须明确声明他的意图,然后机器会对其进行检查。假设程序员可能会犯语义错误(图形/手枪/卡)。 继续:程序员必须声明其意图的至少一部分,但是检查机器时机器可以继续运行。假设程序员可能会犯一个笔误(整数/字符串),而不会犯语义上的错误(图形/手枪/卡)。 鸭式打字:程序员无需表达任何意图,机器无需检查。假定程序员不太可能犯笔误或语义错误。 解决接口和一般类型是否足以测试笔误和语义错误超出了此答案的范围。完整的讨论将不得不考虑构建时编译器技术,自动化测试方法,运行时/热点编译以及许多其他问题。 公认的是,故意夸大了“ 11”的例子。实际的示例将涉及更丰富的类型,这些类型将提供更多线索来消除方法的歧义。
辽躺
吞睫素
壬驴拿歪竞
苏髓骗撩
勺的驴吓识
接口开始(可以根据需要经常使用它来创建一个枚举器,该枚举器将输出一系列T \,但是可能会有不同的请求产生不同的序列),然后从中派生出接口
,该接口的行为如上,但保证每个请求都返回相同的序列。可变的收集类型可以支持
所需的所有成员,但是由于突变后收到的枚举请求将报告与之前提出的请求不同的顺序,因此它不遵守
合同。 接口被视为封装了超出其成员签名范围的合同的能力是使基于接口的编程在语义上比简单的鸭子键入更强大的功能之一。