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

时间:2008-10-13 15:02:04

标签: java interface abstract-class

当您使用抽象类来实现接口时,Java中会发生奇怪的事情:某些接口的方法可能完全丢失(即既不存在抽象声明也不存在实际实现),但编译器不会抱怨。

例如,给定接口:

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

以下抽象类在没有警告或错误的情况下快速编译:

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

你能解释一下原因吗?

6 个答案:

答案 0 :(得分:148)

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

按照您的示例代码,尝试创建AbstractThing的子类,而不实现m2方法,并查看编译器为您提供的错误。它会强制你实现这个方法。

答案 1 :(得分:33)

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

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

答案 2 :(得分:7)

没关系。要理解上述内容,您必须首先了解抽象类的本质。它们在这方面类似于接口。这就是Oracle对此here所说的话。

  

抽象类与接口类似。您无法实例化它们,并且它们可能包含使用或不使用实现声明的方法组合。

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

//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);
}

......正如你所看到的,这也很好地编译。仅仅因为,就像抽象类一样,接口无法实例化。因此,不需要明确提及其父母"中的方法。但是,所有父方法签名都隐式地成为扩展接口或实现抽象类的一部分。因此,一旦适当的类(可以实例化的类)扩展了上述内容,就需要确保实现每个抽象方法。

希望有帮助...和Allahu' alam!

答案 3 :(得分:4)

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

答案 4 :(得分:2)

  

抽象类实现接口时

     

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

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

答案 5 :(得分:1)

实现这些方法不需要抽象类。因此即使它实现了一个接口,接口的抽象方法也可以保持抽象。如果您尝试在具体类中实现接口(即不是抽象),并且您没有实现抽象方法,编译器将告诉您:实现抽象方法或将类声明为抽象。