Java 为什么在多重继承中而不是在接口中出现歧义

Java 为什么在多重继承中而不是在接口中出现歧义,java,Java,我们如何在接口中实现模糊性?我们不能使用抽象类来实现歧义吗?我认为抽象类也可以收集完全抽象的方法。那么为什么我们需要接口呢。一个完全抽象的类和一个接口在表面上看起来是一样的,但是在启动时它们是非常不同的。采取以下行动: public interface WildAnimal { ... } public interface TamePet { ... } public class Dog implements WildAnimal, TamePet { ... } abstract class

我们如何在接口中实现模糊性?我们不能使用抽象类来实现歧义吗?我认为抽象类也可以收集完全抽象的方法。那么为什么我们需要接口呢。

一个完全抽象的类和一个接口在表面上看起来是一样的,但是在启动时它们是非常不同的。采取以下行动:

public interface WildAnimal { ... }
public interface TamePet { ... }
public class Dog implements WildAnimal, TamePet { ... }

abstract class BadWildAnimal { ... } // fully abstract
abstract class BadTamePet extends BadWildAnimal{ ... } // fully abstract 
public abstract class BadDog extends BadTamePet { ... } // defines all methods of both BadAnimal and BadPet
在我的代码中,我有一只狗。这只狗可以野生或驯服,我可以通过以下方法传递:

WildAnimal myDog = new Dog(); // I will treat this object as though it is a wild animal
TamePet trainedDog = trainMyDog(myDog); // I will treat this object as though it is a trained pet

protected Dog trainMyDog(Dog someDog) { ... }
我在这里说的是,我从一只野生动物开始(在本例中,它是一只狗),我训练它,使它成为一只驯服的宠物。
trainMyDog(dogsomedog)
方法只知道它将得到一只狗。它会对它做点什么,然后还给它一条狗。打电话的人知道,它会给它一只
野生动物的狗
,并会取回一只
驯服的宠物

这里需要知道的重要一点是,
myDog
对象只能看到并访问在
WildAnimal
中定义的方法。
trainedDog
对象只能查看和访问
TamePet
中定义的方法。即使Dog实现了这两种方法,这些对象也只能作用于接口定义的方法。这些对象不属于
Dog
类。它们分别属于
野生动物
驯养狗

如果我们以另一种方式执行此操作,那么我们的代码将完全不同。我们只能启动一个类,那就是class
BadDog
。它既是一个
BadWildAnimal
类,同时又是一个
BadTamePet
,这在逻辑上是没有意义的

代码看起来也很奇怪:

BadDog myDog = new BadDog();
BadDog trainedDog = trainMyDog(BadDog someDog);

protected BadDog trainMyDog(BadDog someDog) { ... }
如果其他人后来来阅读您的代码,或者如果您几年后回去更新您的代码,那么上面的代码就没有意义了。您可以尝试进行类型转换,但是读取和传递对象变得更加困难。但是,如果您使用接口,很明显发生了什么以及如何进行


在这些示例中,接口使代码更易于阅读,并确保我正确使用了对象。
Dog
类中可能有一个名为
biteTheMailman()
的方法,但如果该方法是在
WildAnimal
接口中定义的,则只有
myDog
对象可以这样做。我不能让我的
培训日志
那样做

一个完全抽象的类和一个接口在表面上看起来是一样的,但是在初始化时它们是非常不同的。采取以下行动:

public interface WildAnimal { ... }
public interface TamePet { ... }
public class Dog implements WildAnimal, TamePet { ... }

abstract class BadWildAnimal { ... } // fully abstract
abstract class BadTamePet extends BadWildAnimal{ ... } // fully abstract 
public abstract class BadDog extends BadTamePet { ... } // defines all methods of both BadAnimal and BadPet
在我的代码中,我有一只狗。这只狗可以野生或驯服,我可以通过以下方法传递:

WildAnimal myDog = new Dog(); // I will treat this object as though it is a wild animal
TamePet trainedDog = trainMyDog(myDog); // I will treat this object as though it is a trained pet

protected Dog trainMyDog(Dog someDog) { ... }
我在这里说的是,我从一只野生动物开始(在本例中,它是一只狗),我训练它,使它成为一只驯服的宠物。
trainMyDog(dogsomedog)
方法只知道它将得到一只狗。它会对它做点什么,然后还给它一条狗。打电话的人知道,它会给它一只
野生动物的狗
,并会取回一只
驯服的宠物

这里需要知道的重要一点是,
myDog
对象只能看到并访问在
WildAnimal
中定义的方法。
trainedDog
对象只能查看和访问
TamePet
中定义的方法。即使Dog实现了这两种方法,这些对象也只能作用于接口定义的方法。这些对象不属于
Dog
类。它们分别属于
野生动物
驯养狗

如果我们以另一种方式执行此操作,那么我们的代码将完全不同。我们只能启动一个类,那就是class
BadDog
。它既是一个
BadWildAnimal
类,同时又是一个
BadTamePet
,这在逻辑上是没有意义的

代码看起来也很奇怪:

BadDog myDog = new BadDog();
BadDog trainedDog = trainMyDog(BadDog someDog);

protected BadDog trainMyDog(BadDog someDog) { ... }
如果其他人后来来阅读您的代码,或者如果您几年后回去更新您的代码,那么上面的代码就没有意义了。您可以尝试进行类型转换,但是读取和传递对象变得更加困难。但是,如果您使用接口,很明显发生了什么以及如何进行

在这些示例中,接口使代码更易于阅读,并确保我正确使用了对象。
Dog
类中可能有一个名为
biteTheMailman()
的方法,但如果该方法是在
WildAnimal
接口中定义的,则只有
myDog
对象可以这样做。我不能让我的
培训日志
那样做