Java 为什么实现接口的抽象类会错过接口方法之一的声明/实现?
在Java中,当您使用抽象类实现接口时,会发生一件奇怪的事情:接口的某些方法可能完全丢失,即既没有抽象声明也没有实际实现,但编译器不会抱怨 例如,给定接口:Java 为什么实现接口的抽象类会错过接口方法之一的声明/实现?,java,interface,abstract-class,Java,Interface,Abstract Class,在Java中,当您使用抽象类实现接口时,会发生一件奇怪的事情:接口的某些方法可能完全丢失,即既没有抽象声明也没有实际实现,但编译器不会抱怨 例如,给定接口: public interface IAnything { void m1(); void m2(); void m3(); } public interface IAnything { int i; void m1(); void m2(); void m3(); } 以下抽象类在没有警告或错误的情况下轻松编
public interface IAnything {
void m1();
void m2();
void m3();
}
public interface IAnything {
int i;
void m1();
void m2();
void m3();
}
以下抽象类在没有警告或错误的情况下轻松编译:
public abstract class AbstractThing implements IAnything {
public void m1() {}
public void m3() {}
}
你能解释一下原因吗?那是因为如果一个类是抽象的,那么根据定义,你需要创建它的子类来实例化。编译器需要这些子类来实现抽象类遗漏的任何接口方法 按照您的示例代码,尝试在不实现m2方法的情况下创建AbstractThing的子类,并查看编译器给您带来的错误。它将迫使您实现此方法。非常好。 不能实例化抽象类。。但抽象类可用于容纳m1和m3的通用实现。 因此,如果m2实现对于每个实现是不同的,但m1和m3不是。您可以使用不同的m2实现创建不同的具体IAnything实现,并从AbstractThing中派生出来,这符合DRY原则。验证接口是否完全为抽象类实现是徒劳的
更新:有趣的是,我发现C将其作为编译错误强制执行。在这种情况下,您必须复制方法签名,并在抽象基类中使用“abstract public”作为前缀。。每天都有新东西:实现这些方法不需要抽象类。因此,即使它实现了一个接口,接口的抽象方法也可以保持抽象。如果你试图在一个具体的类中实现一个接口,即非抽象类,而你没有实现抽象方法,编译器会告诉你:要么实现抽象方法,要么将类声明为抽象类。接口指的是一个没有实现其方法的类,而只是声明。 另一方面,抽象类是一个类,它可以实现一些方法,也可以实现一些只声明而不实现的方法。
当我们实现抽象类的接口时,这意味着抽象类继承了接口的所有方法。因为,在抽象类中实现所有方法并不重要,但是它也是通过继承来实现抽象类的,所以抽象类可以在接口中留下一些方法而不在这里实现。但是,当这个抽象类被某个具体类继承时,它们必须实现抽象类中所有未实现的方法。这很好。要理解上述内容,您必须首先理解抽象类的本质。在这方面,它们类似于接口。这就是甲骨文对此的说法 抽象类类似于接口。您不能实例化它们,它们可能包含使用或不使用实现声明的方法的混合 因此,您必须考虑当一个接口扩展另一个接口时会发生什么。例如
//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);
}
。。。正如您所看到的,这也编译得非常好。原因很简单,就像抽象类一样,接口不能实例化。因此,它不需要显式地提及其父级的方法。但是,所有父方法签名都隐式地成为扩展接口或实现抽象类的一部分。因此,一旦可以实例化的适当类扩展了上述内容,就需要确保实现每个抽象方法
希望这有助于。。。阿拉胡阿拉姆
当抽象类实现接口时
在关于接口的一节中,注意到
实现接口必须实现接口的所有方法。
但是,可以定义一个不实现所有功能的类
如果类声明为
摘要比如说,
在这种情况下,类X必须是抽象的,因为它不完全是抽象的
实现Y,但是类XX实际上实现Y
参考:给定接口:
public interface IAnything {
void m1();
void m2();
void m3();
}
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();
}
因此,您可以保留部分或所有这些抽象方法未实现,就像您在抽象类扩展另一个抽象类的情况下所做的那样
实现接口时,所有接口方法必须在派生类中实现的规则仅适用于具体的类实现,即它本身不是抽象的
如果您确实计划用它创建一个抽象类,那么没有规则说您必须实现所有接口方法。注意,在这种情况下,必须声明
作为抽象的派生类我认为编译器仍然应该对未完全实现接口的抽象类发出警告,因为这样您就需要查看2个类定义,而不是1个,以查看子类中需要什么。但这是语言/编译器的限制。这不是一个好主意,因为通常会有很多抽象类,而“错误”警告很快就会淹没你,导致你错过“正确”警告。如果你仔细想想,“abstract”关键字专门用来告诉编译器取消对该类的警告。@workmad-如果您有接口方法子集的通用实现,那么将其分解到单独的基类中会更有意义,而不是一个地方代码,要求您在抽象类。如果您这样做,那么子类的实现者将继承这种非行为,而编译器不会告诉他们有问题。我认为workmad可能建议您在没有方法体的抽象类中定义方法,并将它们标记为抽象。对我来说似乎不是个坏主意。这是一个有趣的观点。它让我认为抽象类实际上是具体的接口,即带有一些具体方法的接口,而不是带有一些抽象方法的类。。。。两者兼而有之。但有一点可以肯定,它们是不可实例化的,不能创建抽象类的对象。因此,只要没有为抽象类提供实现,就无法为IAnything创建对象。所以这对于编译器来说是绝对好的。编译器希望,任何实现IAnything的非抽象类都必须实现在IAnything之外声明的所有方法。由于必须扩展和实现AbstractThing才能创建对象,如果该实现没有实现AbstractThing遗漏的IAnything方法,编译器将抛出一个错误。我有一个具体的类,它在与此相同的场景中扩展了自己的AbstractThing,尽管我没有在接口中实现其中一个方法,但它的编译过程令人费解。现在它正在做我期望的事情,但我不知道是什么原因导致了它以前的成功。我怀疑我没有:我有一个文件。您可以使用javap IAnything.class生成第二个代码段,看到类似问题的答案。