Java 接口解决了“问题”吗;致命的死亡钻石“;问题

Java 接口解决了“问题”吗;致命的死亡钻石“;问题,java,interface,multiple-inheritance,Java,Interface,Multiple Inheritance,接口能解决问题吗 我不这么认为,例如: // A class implementing two interfaces Interface1 and Interface2. // Interface1 has int x=10 and Interface2 has int x = 20 public class MultipleInterface implements Interface1, Interface2{ public void getX(){ System.

接口能解决问题吗

我不这么认为,例如:

// A class implementing two interfaces Interface1 and Interface2.
// Interface1 has int x=10 and Interface2 has int x = 20

public class MultipleInterface implements Interface1, Interface2{

    public void getX(){
        System.out.println(x);
    }
}
class Base {
    int x = 10;
}

interface Interface {
    int x = 20;
}

class SingleInheritance implements Interface {
    int y = 2 * x; // ok
}

class MultipleInheritance extends Base implements Interface {
    int y = 2 * x; // compile-time error
    int z = 2 * Interface.x; // ok
}

void aMethod(MultipleInheritance  arg) {
    System.out.println("arg.x = " + arg.x); // compile-time error
    System.out.println("x = " + Interface.x); // ok
}
这里我们得到一个模糊的
x

虽然接口是解决方法歧义的好方法,但我想它们在变量的情况下会失败


我说得对吗?如果我遗漏了什么,请告诉我。

当一个类从父接口继承了两个变量时,Java坚持使用所讨论的变量名必须是完全限定的。这就解决了问题。见:

一个类可以继承多个同名字段。这种情况本身不会导致编译时错误。但是,在类的主体中,任何试图通过其简单名称引用任何此类字段的尝试都将导致编译时错误,因为此类引用是不明确的

类似的语句适用于接口()

中的示例代码非常优秀。下面是另一个例子:

// A class implementing two interfaces Interface1 and Interface2.
// Interface1 has int x=10 and Interface2 has int x = 20

public class MultipleInterface implements Interface1, Interface2{

    public void getX(){
        System.out.println(x);
    }
}
class Base {
    int x = 10;
}

interface Interface {
    int x = 20;
}

class SingleInheritance implements Interface {
    int y = 2 * x; // ok
}

class MultipleInheritance extends Base implements Interface {
    int y = 2 * x; // compile-time error
    int z = 2 * Interface.x; // ok
}

void aMethod(MultipleInheritance  arg) {
    System.out.println("arg.x = " + arg.x); // compile-time error
    System.out.println("x = " + Interface.x); // ok
}

编辑 Java8为方法引入了一种有限形式的多重继承,因为接口现在可以声明子接口和实现类可以继承。由于一个类可以实现多个接口,这可能会导致歧义,因为具有相同签名的不同默认方法可以从多个接口继承。1 Java使用优先级方案来指定实际继承的默认方法。当优先级方案无法生成单个赢家时,它需要显式重写继承的默认方法

请注意,Java在任何情况下都没有菱形问题,这是一个非常特定的问题子类,可以与多重继承一起出现。2“菱形”部分指的是类继承图的形状,这是产生问题所必需的。在C++中,如果A类继承了两个类B和C,则会产生钻石问题。每个类继承自一个公共基类D。在这种情况下,D的任何公共成员最终出现在A中,两次继承一次B,一次通过C.,每当A的实例被构造或销毁时,D的构造函数或析构函数最终会被调用两次(通常会带来灾难性的后果,因此名称中有“死亡”部分)。C++通过提供虚拟继承来解决这些问题。(有关详细信息,请参见讨论。)

1注意“独特”一词的用法。如果相同的默认方法通过两个父接口继承,而这两个父接口又扩展了定义默认方法的公共基接口,则没有问题;默认方法是简单地继承的


2其他多重继承问题,如Java中可能出现的接口字段、静态方法和默认方法的歧义,在技术上与菱形问题(实际上是致命的死亡钻石问题)无关。然而,许多关于这个问题的文献(以及这个答案的早期版本)最终都将所有多重继承问题归为“死亡钻石”一类。我想这个名字太酷了,不能只在技术上合适的时候才使用。

不,你没有。接口没有任何变量,除了静态的最终变量

如果您真的编写、编译和执行这些接口和类,您将得到答案。该
x
变量不是类成员,因此不存在歧义


这是通过编写代码并让JDK告诉您,您可以轻松回答的问题之一。这比在这里询问要快。

接口不能有属性。当你写这篇文章时:

public interface Foo {
    int x;
}
在引擎盖下,它隐式地转换为一个常量,类似这样:

public interface Foo {
    public static final int x;
}
public class Baz implements Foo, Bar {
    private int y = Foo.x + Bar.x;
}
假设您有另一个具有类似命名常量的接口:

public interface Bar {
    int x;
}
如果要在同时实现
Foo
Bar
的类中使用
x
值,则必须限定这些常量,不留任何歧义的余地,如下所示:

public interface Foo {
    public static final int x;
}
public class Baz implements Foo, Bar {
    private int y = Foo.x + Bar.x;
}

所以这里没有钻石。无论如何,现在不赞成在接口中声明常量,大多数情况下,最好使用枚举来达到同样的效果。

Java阻止多个具体/抽象类继承,但不能阻止多个接口继承。使用多接口继承可以继承抽象方法,而不是实现。请参阅这篇文章,并提供一些很好的解释和示例:

致命的死亡钻石问题

class A
{
void eat()
{
    print("I am eating Apple")
}
}
类B和C扩展并重写eat()方法

如果java有多重继承?在以下情况下会发生什么

 class D extends B ,C
{
//which eat() method will be inherited here for class D ? a problem  ? ?
}

致命的死亡钻石是变量的问题,但虚拟方法的问题更大。如果类
Moo1
Moo2
都继承自类
Foo
并重写抽象虚拟函数
Bar
,并且如果类
Zoo
被允许继承自
Moo1
Moo2
,而无需添加其自身对
Bar
的重写,还不清楚
Zoo
Bar
方法应该做什么。接口通过要求实现接口的每个类都必须为所有接口成员提供自己的实现,并通过指定接口的所有成员在直接或间接扩展接口的所有接口中都被视为相同,从而避免了该问题。因此,在上述情况下,如果
Foo
等是接口而不是类,那么任何实现
Zoo
的类都需要实现
Foo.Bar
,这将是
Moo1.Bar
Moo2.Bar
Zoo.Bar

的同义词,您能用代码说明您的意思吗?据我所知,变量不能从接口继承。你能评论一下在关于Java8的“编辑”一节中你想象的具体问题场景吗?(仅供参考,此答案引用自。)@TedHopp-I