为什么实现接口的抽象类可能会错过接口方法之一的声明/实现?

在使用抽象类来实现一个接口时,Java中会出现一个奇怪的事情:一些接口的方法可能完全丢失(即,既没有抽象声明也没有实际的实现),但是编译器不会抱怨。

例如,给定接口:

public interface IAnything { void m1(); void m2(); void m3(); } 

下面的抽象类快速编译没有警告或错误:

 public abstract class AbstractThing implements IAnything { public void m1() {} public void m3() {} } 

你能解释一下为什么?

那是因为如果一个类是抽象的,那么根据定义,你需要创build它的子类来实例化。 子类(编译器)需要实现抽象类省略的任何接口方法。

遵循您的示例代码,请尝试在不实现m2方法的情况下创buildAbstractThing的子类,并查看编译器为您提供的错误。 这将迫使你实施这个方法。

完美无瑕。
你不能实例化抽象类..但抽象类可以用来容纳m1()和m3()的常见实现。
所以如果 m2()的实现不同,每个实现,但m1和m3不是。 你可以创build不同的具体的IAnything实现,只是不同的m2实现,并从AbstractThing派生 – 遵循DRY原则。 validation接口是否完全实现为抽象类是徒劳的..

更新 :有趣的是,我发现C#强制这个作为编译错误。 你被迫复制方法签名,并在这个场景的抽象基类中用'abstract public'作为前缀。(每天都有新东西:)

没关系。 要理解上面的内容,你首先要了解抽象类的本质。 它们在这方面与接口相似。 这就是Oracle 在这里所说的。

抽象类与接口类似。 你不能实例化它们,它们可能包含一个声明有或没有实现的混合方法。

所以你必须考虑当一个接口扩展另一个接口时会发生什么。 例如 …

 //Filename: Sports.java public interface Sports { public void setHomeTeam(String name); public void setVisitingTeam(String name); } //Filename: Football.java public interface Football extends Sports { public void homeTeamScored(int points); public void visitingTeamScored(int points); public void endOfQuarter(int quarter); } 

…你可以看到,这也编译得很好。 简单地说,就像抽象类一样,一个接口不能被实例化。 所以,没有必要明确提到“父母”的方法。 但是,所有的父方法签名都会隐式地成为扩展接口或实现抽象类的一部分。 因此,一旦适当的类(可以被实例化)扩展了上述内容,将需要确保每一个抽象方法都被实现。

希望有助于…和阿拉胡阿拉姆!

接口意味着一个没有实现它的方法的类,只是声明而已。
另一方面,抽象类是一个只能声明,不实现的可以有一些方法实现的类。
当我们实现一个抽象类的接口时,这意味着抽象类inheritance了接口的所有方法。 因为在抽象类中实现所有的方法并不重要,但是抽象类也是通过inheritance来实现的,所以抽象类可以在接口中保留一些方法而不需要实现。 但是,当这个抽象类被某个具体的类inheritance时,它们必须在抽象类中实现那些未实现的方法。

当一个抽象类实现一个接口

在接口部分,有人指出,实现接口的类必须实现接口的所有方法。 但是,可以定义一个不实现所有接口方法的类,只要这个类声明为抽象的。 例如,

 abstract class X implements Y { // implements all but one method of Y } 
 class XX extends X { // implements the remaining method in Y } 

在这种情况下,X类必须是抽象的,因为它没有完全实现Y,但是XX类实际上实现了Y.

参考: http : //docs.oracle.com/javase/tutorial/java/IandI/abstract.html

抽象类不需要实现这些方法。 所以即使它实现了一个接口,接口的抽象方法也可以保持抽象。 如果你试图在一个具体的类中实现一个接口(即不是抽象的)而你没有实现抽象方法,编译器会告诉你:实现抽象方法或者声明类是抽象的。

鉴于界面:

 public interface IAnything { int i; void m1(); void m2(); void m3(); } 

这是Java实际上看到它的方式:

 public interface IAnything { public static final int i; public abstract void m1(); public abstract void m2(); public abstract void m3(); } 

因此,您可以将一些(或全部)这些abstract方法实现,就像在abstract类中扩展另一个abstract类一样。

当你implement一个interface ,所有interface方法必须在派生class实现的规则,只适用于具体的class实现(即不是abstract本身)。

如果你的确打算创build一个abstract class ,那么没有规则说你必须implement所有的interface方法(注意,在这种情况下,必须将派生class声明为abstract class