有时我们有几个类具有相同签名的某些方法,但是它们与声明的Java接口不对应.例如,两者JTextField和JButton(在其他几个中 javax.swing.*)都有一种方法
public void addActionListener(ActionListener l)
Run Code Online (Sandbox Code Playgroud)
现在,假设我希望对具有该方法的对象执行某些操作; 那么,我想要一个界面(或者自己定义它),例如
public interface CanAddActionListener {
public void addActionListener(ActionListener l);
}
Run Code Online (Sandbox Code Playgroud)
所以我可以写:
public void myMethod(CanAddActionListener aaa, ActionListener li) {
aaa.addActionListener(li);
....
Run Code Online (Sandbox Code Playgroud)
但是,遗憾的是,我不能:
JButton button;
ActionListener li;
...
this.myMethod((CanAddActionListener)button,li);
Run Code Online (Sandbox Code Playgroud)
这个演员是非法的.编译器知道它JButton 不是 a CanAddActionListener,因为类没有声明实现该接口...... 但是它"实际"实现了它.
这有时会带来不便 - 而Java本身已经修改了几个核心类来实现由旧方法构成的新接口(String implements CharSequence例如).
我的问题是:为什么会这样?我理解声明一个类实现接口的实用程序.但无论如何,看看我的例子,为什么编译器不能推断出类JButton"满足"接口声明(查看它内部)并接受转换?这是编译器效率的问题还是存在更多基本问题?
我对答案的总结:这是一个Java可以允许一些"结构类型"(一种鸭子打字 - 但在编译时检查)的情况.它没有.除了一些(对我来说不清楚)性能和实现困难之外,还有一个更为基本的概念:在Java中,接口的声明(以及一般来说,所有内容)并不仅仅是结构性的(具有方法)这些签名)但语义:这些方法应该实现一些特定的行为/意图.因此,一个在结构上满足某些接口的类(即,它具有所需签名的方法)并不一定在语义上满足它(一个极端的例子:回想一下"标记接口",它甚至没有方法!).因此,Java可以断言一个类实现了一个接口,因为(并且只是因为)已经显式声明了它.其他语言(Go,Scala)有其他语言.