为什么歧义发生在多重继承而非接口中

时间:2015-11-09 18:51:31

标签: java

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

1 个答案:

答案 0 :(得分:0)

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

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) { ... }

我在这里说的是我从WildAnimal开始(在这种情况下,它是一只狗),我训练了狗,现在它是一个TamePet。 trainMyDog(Dog someDog)方法只知道它会变成一只狗。它会做一些事情,然后回馈一只狗。来电者知道它会给它一只WildAnimal的狗并且会找回TamePet

这里要知道的重要一点是myDog对象只能查看并访问WildAnimal中定义的方法。 trainedDog对象只能查看并访问TamePet中定义的方法。尽管Dog实现了两者,但这些对象只能作用于接口定义它们被定义为的那些方法。这些对象不属于Dog类。它们分别是WildAnimalTameDog类型。

如果我们以另一种方式完成此操作,那么我们的代码会完全不同。我们只能启动一个类,即类BadDog。它同时属于BadWildAnimal类和BadTamePet,但它没有逻辑意义。

代码看起来也很奇怪:

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

protected BadDog trainMyDog(BadDog someDog) { ... }

如果其他人稍后来阅读您的代码,或者如果您多年后再更新代码,则上面的代码没有任何意义。您可以尝试进行类型转换,但随后更难以阅读并传递对象成为一件苦差事。但是,如果使用接口,则很明显发生了什么以及它是如何完成的。

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