我正在阅读"The Java Tutorial"(第二次).我刚刚完成了关于接口的部分(再次),但仍然不了解Java接口如何模拟多重继承.是否有比书中更清楚的解释?
如果我们有一个继承自多个接口的类,并且接口具有相同名称的方法,那么我们如何在我的类中实现这些方法?我们如何指定实现哪个接口的方法?
Class A有run()方法和接口B也有run()方法.问题很简单,哪种run()方法在Main课堂上被覆盖,我们将如何证明这一点?为什么此代码中没有冲突(编译时错误)?
class A{
void run(){System.out.println("A class");}
}
interface B{
void run();
}
class Main extends A implements B{
public static void main(String args[]){
Main m = new Main();
m.run();
}
// Overridding method
public void run(){
System.out.println("run method");
}
}
Run Code Online (Sandbox Code Playgroud) 我没有C++经验,而且我来自Java背景.最近,我在接受采访时被问到为什么Java不允许多重继承,答案很简单.但是,我仍然很好奇C++如何处理它,因为它允许你从多个类继承.
具体来说,假设有一个叫做的类MechanicalEngineer,另一个叫做ElectricalEngineer.两者都有一个叫做的方法buildRobot().
如果我们制作第三个类会发生什么RoboticsEngineer,从两个方面都不存在并且不会覆盖该方法,并且您只需调用:
(some instance of RoboticsEngineer).buildRobot()
Run Code Online (Sandbox Code Playgroud)
是否会抛出异常,或者使用其中一个超类的方法?如果是这样,编译器如何知道要使用哪个类?
这段代码完美无缺.方法test()适用于两个接口.引擎盖下究竟发生了什么?这个功能在实际场景中有用吗?
interface A
{
void test();
}
interface B
{
void test();
}
class C implements A, B
{
public void test()
{
System.out.println("abc");
}
}
A a = new C();
a.test();
B b = new C();
b.test();
Run Code Online (Sandbox Code Playgroud) 在英语中,同形异义词对是两个具有相同拼写但含义不同的单词.
在软件工程中,一对同形方法是两种具有相同名称但要求不同的方法.让我们看一个人为的例子,让问题尽可能清晰:
interface I1 {
/** return 1 */
int f()
}
interface I2 {
/** return 2*/
int f()
}
interface I12 extends I1, I2 {}
Run Code Online (Sandbox Code Playgroud)
我该如何实施I12?C#有办法做到这一点,但Java没有.所以唯一的方法是破解.怎样才能最可靠地使用反射/字节码技巧/等(也就是说它不一定是一个完美的解决方案,我只想要一个效果最好的解决方案)?
请注意,我无法合法反向工程的一些现有的闭源大量遗留代码需要一个类型参数,I12并将I12两者都委托给I1作为参数的代码和作为参数的代码I2.所以基本上我需要让它的一个实例I12知道什么时候它应该起作用I1,什么时候它应该起作用I2,我相信可以通过在直接调用者的运行时查看字节码来完成.我们可以假设调用者没有使用反射,因为这是简单的代码.问题是作者I12没想到Java会f从两个接口合并,所以现在我必须想出最好的解决问题的方法.没有什么叫I12.f(显然如果作者写了一些实际调用的代码I12.f,他会在出售之前注意到这个问题).
请注意,我实际上是在寻找这个问题的答案,而不是如何重构我无法改变的代码.我正在寻找可行的最佳启发式或者如果存在的话,可以找到精确的解决方案.请参阅Gray的答案以获得有效示例(我确信有更强大的解决方案).
这是一个具体的例子,说明两个接口内的单应方法问题是如何发生的.这是另一个具体的例子:
我有以下6个简单的类/接口.它类似于剧院周围的商业和在其中表演的艺术家.为了简单起见,我们假设它们都是由不同的人创建的.
Set 代表一组,如集合论:
interface Set {
/** Complements this set,
i.e: all elements in the set …Run Code Online (Sandbox Code Playgroud) 假设我有以下内容:
public interface Filter<E> {
public boolean accept(E obj);
}
Run Code Online (Sandbox Code Playgroud)
和
import java.io.File;
import java.io.FilenameFilter;
public abstract class CombiningFileFilter extends javax.swing.filechooser.FileFilter
implements java.io.FileFilter, FilenameFilter {
@Override
public boolean accept(File dir, String name) {
return accept(new File(dir, name));
}
}
Run Code Online (Sandbox Code Playgroud)
就目前而言,您可以使用javac进行编译CombiningFileFilter.但是,如果你还决定实施Filter<File>中CombiningFileFilter,你会得到以下错误:
CombiningFileFilter.java:9: error: reference to accept is ambiguous,
both method accept(File) in FileFilter and method accept(E) in Filter match
return accept(new File(dir, name));
^
where E is a type-variable:
E extends Object declared in interface …Run Code Online (Sandbox Code Playgroud) 有两个接口B,C每个接口都有相同的方法public m1()
class A implements B and C
Run Code Online (Sandbox Code Playgroud)
如果类A必须实现方法m1(),实现的方法将是哪个接口?
请考虑以下代码:
public interface A {
public A another();
}
public interface B {
public B another();
}
public interface AB extends A,B {
public AB another();
}
Run Code Online (Sandbox Code Playgroud)
这会导致编译错误AB:
B型和A型不兼容; 两者都定义了另一个(),但具有不相关的返回类型
我已经看到了这个问题,并按照接受的答案中的不兼容性示例 - 即
public interface C {
public void doSomething();
}
public interface D {
public boolean doSomething();
}
public interface CD extends C,D {
}
Run Code Online (Sandbox Code Playgroud)
但是,在这种情况下,返回类型实际上是不兼容的 - 返回类型不能同时为void和布尔值.然而,在上面的示例中,another()返回类型AB是a A和a B,因此可以实现两个扩展接口.
此外,看过JLS(8.4.8,8.4.8.3,8.4.8.4)后,我不太明白为什么我的上面的例子非法.任何人都可以向我解释这个吗?
其次,是否有任何解决方案/解决方法,此除重复的合同要求A或B在AB?
最近,在阅读Programming Languages and Practice book 的一些文章后,提到Java 中的多接口继承不会遇到与C++ 中的多类继承相同的问题。
但我不明白为什么会发生这种情况。java如何在C++实现中存在错误时使用多接口继承??
有没有办法替换 C++ 中的多重继承以避免实现问题?
为了让最后一条语句更具体,让我们说我们有:
class A {...};
class B : public A {...};
class C : public A {...};
class D : public B, public C {...};
Run Code Online (Sandbox Code Playgroud)
然后类 D 继承类 B,C,它们都继承类 A。所以如果 A 有一个字段变量,那么 B,C 将具有相同的变量名称,那么 D 将具有什么变量(从 B 或 C 继承)。为了避免这种情况我们可以编写没有多重继承但具有相似结果的上述代码吗?
这个问题不是重复的,因为它不关注示例中的最终继承是什么,而是了解 Java-C++ 多重继承之间的区别(参见上面的第一个问题)以及是否有建议克服的方法一些多重继承问题(如上)。