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

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

例如,考虑到界面:

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

下面的抽象类在没有警告或错误的情况下被愉快地编译:

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

你能解释一下为什么吗?

143313 次浏览

这是因为如果一个类是抽象的,那么根据定义,您需要创建它的子类来实例化。子类(由编译器)将需要实现抽象类遗漏的任何接口方法。

按照您的示例代码,尝试在不实现 m2方法的情况下创建 AbstractThing的子类,并查看编译器会给您带来什么错误。它将强制您实现此方法。

非常好。
您不能实例化抽象类. . 但是抽象类可以用来容纳 m1()和 m3()的通用实现。
因此,如果 m2()的实现对于每个实现都是不同的,但是 m1和 m3没有不同。您可以使用不同的 m2实现创建不同的具体的 IAnything 实现,并从 AbstractThing 派生——遵循 DRY 原则。验证接口是否完全为抽象类实现是徒劳的。.

更新 : 有趣的是,我发现 C # 将其作为编译错误强制执行。在这个场景中,您必须复制方法签名,并在抽象基类中以“抽象公共”作为前缀。.(每天都有新鲜事)

实现这些方法不需要抽象类。因此,即使它实现了一个接口,接口的抽象方法仍然可以是抽象的。如果你试图在一个具体的类中实现一个接口(即不是抽象的) ,但是你没有实现编译器会告诉你的抽象方法: 要么实现抽象方法,要么将类声明为抽象的。

接口是指没有其方法的实现,只有声明的类。
另一方面,抽象类是一个类,它可以有一些方法的实现,以及一些只有声明,没有实现的方法。
当我们实现一个抽象类的接口时,它意味着这个抽象类继承了接口的所有方法。因为,在抽象类中实现所有的方法并不重要,但是对于抽象类来说(通过继承) ,所以抽象类可以在接口中留下一些方法而不在这里实现。但是,当这个抽象类被某个具体的类继承时,它们必须实现抽象类中所有未实现的方法。

没关系。要理解上述内容,首先必须理解抽象类的本质。它们在这方面类似于接口。这就是 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);
}

正如你所看到的,这个也编译得非常好。仅仅是因为,就像抽象类一样,接口不能被实例化。因此,它不需要显式地提及来自其“父”的方法。但是,所有的父方法签名都隐式地成为扩展接口或实现抽象类的一部分。因此,一旦一个合适的类(一个可以实例化的类)扩展了上述内容,就需要确保每个抽象方法都得到了实现。

希望能有所帮助,真主保佑!

抽象类实现接口时

在接口一节中,注意到一个类 实现一个接口必须实现该接口的所有方法。 但是,可以定义一个不实现所有 接口的方法,前提是该类被声明为 例如,

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类所做的那样。

当您使用 implementinterface时,所有 interface方法必须在派生的 class中实现的规则仅适用于具体的 class实现(即,它本身不是 abstract)。

如果您确实计划用它创建一个 abstract class,那么没有规则说必须将所有 interface方法都声明为 implement(注意,在这种情况下,必须将派生的 class声明为 abstract)