当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《为什么实现接口的抽象类可能会错过接口方法之一的声明/实现?》经验,为你挑选了3个好方法。

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

例如,给定接口:

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

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

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

你能解释一下原因吗?



1> Bill the Liz..:

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

按照您的示例代码,尝试在AbstractThing不实现m2方法的情况下创建子类,并查看编译器为您提供的错误.它会强制您实现此方法.


我认为workmad可能建议你在没有方法体的情况下在抽象类中定义方法并将它们标记为抽象.对我来说似乎不是一个坏主意.
@workmad - 如果你有一个接口方法子集的通用实现,那么将它分解为一个单独的基类更有意义(DRY胜过一个地方的代码)
*要求*将空方法实现放在抽象类中是危险的.如果你这样做,那么子类的实现者将继承这种非行为,而编译器不会告诉他们存在问题.
这不是一个好主意,因为通常会有很多抽象类,"错误"警告会很快压倒你,导致你错过'真正的'警告.如果你考虑一下,'abstract'关键字专门用于告诉编译器压制该类的警告.

2> Gishu..:

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

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



3> Grateful..:

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

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

希望有助于......和Allahu'阿拉姆!

推荐阅读
oDavid_仔o_880
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有