简体   繁体   English

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

[英]Why an abstract class implementing an interface can miss the declaration/implementation of one of the interface's methods?

A curious thing happens in Java when you use an abstract class to implement an interface: some of the interface's methods can be completely missing (ie neither an abstract declaration or an actual implementation is present), but the compiler does not complain. 当您使用抽象类实现接口时,Java中发生了一件奇怪的事情:某些接口的方法可能会完全丢失(即既没有抽象声明也没有实际的实现),但是编译器不会抱怨。

For example, given the interface: 例如,给定接口:

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

the following abstract class gets merrily compiled without a warning or an error: 以下抽象类在没有警告或错误的情况下得到了愉快的编译:

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

Can you explain why? 你能解释为什么吗?

That's because if a class is abstract, then by definition you are required to create subclasses of it to instantiate. 那是因为如果一个类是抽象的,那么根据定义,您需要创建它的子类来实例化。 The subclasses will be required (by the compiler) to implement any interface methods that the abstract class left out. 将需要子类(编译器)来实现抽象类遗漏的任何接口方法。

Following your example code, try making a subclass of AbstractThing without implementing the m2 method and see what errors the compiler gives you. 按照您的示例代码,尝试在不实现m2方法的情况下构造AbstractThing的子类,并查看编译器给您带来了哪些错误。 It will force you to implement this method. 它将迫使您实现此方法。

Perfectly fine. 很好。
You can't instantiate abstract classes.. but abstract classes can be used to house common implementations for m1() and m3(). 您无法实例化抽象类。但是抽象类可用于容纳m1()和m3()的常见实现。
So if m2() implementation is different for each implementation but m1 and m3 are not. 因此, 如果每个实现的m2()实现都不相同,但m1和m3则不同。 You could create different concrete IAnything implementations with just the different m2 implementation and derive from AbstractThing -- honoring the DRY principle. 您可以使用不同的m2实现创建不同的具体IAnything实现,并从AbstractThing派生而出-遵守DRY原理。 Validating if the interface is completely implemented for an abstract class is futile.. 验证接口是否完全为抽象类实现是徒劳的。

Update : Interestingly, I find that C# enforces this as a compile error. 更新 :有趣的是,我发现C#将其强制为编译错误。 You are forced to copy the method signatures and prefix them with 'abstract public' in the abstract base class in this scenario.. (something new everyday:) 在这种情况下,您被迫复制方法签名,并在抽象基类中为它们添加“抽象公共”前缀。(每天都有新变化:)

That's fine. 没关系。 To understand the above, you have to understand the nature of abstract classes first. 要了解以上内容,您必须首先了解抽象类的性质。 They are similar to interfaces in that respect. 在这方面,它们类似于接口。 This is what Oracle say about this here . 这就是甲骨文在这里所说的。

Abstract classes are similar to interfaces. 抽象类类似于接口。 You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. 您无法实例化它们,它们可能包含使用或不使用实现声明的方法的混合。

So you have to think about what happens when an interface extends another interface. 因此,您必须考虑一个接口扩展另一个接口时会发生什么。 For example ... 例如 ...

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

... as you can see, this also compiles perfectly fine. ...如您所见,这也可以很好地编译。 Simply because, just like an abstract class, an interface can NOT be instantiated. 仅仅是因为,就像抽象类一样,无法实例化接口。 So, it is not required to explicitly mention the methods from its "parent". 因此,不需要从其“父”对象中明确提及这些方法。 However, ALL the parent method signatures DO implicitly become a part of the extending interface or implementing abstract class. 但是,所有父方法签名都隐式地成为扩展接口或实现抽象类的一部分。 So, once a proper class (one that can be instantiated) extends the above, it WILL be required to ensure that every single abstract method is implemented. 因此,一旦适当的类(可以实例化的类)扩展了上述内容,将需要确保实现每个单独的抽象方法。

Hope that helps... and Allahu 'alam ! 希望有帮助...和阿拉胡阿拉姆!

Interface means a class that has no implementation of its method, but with just declaration. 接口表示一个类,该类没有实现其方法,而只有声明。
Other hand, abstract class is a class that can have implementation of some method along with some method with just declaration, no implementation. 另一方面,抽象类是可以实现某些方法以及仅声明但不实现的方法的类。
When we implement an interface to an abstract class, its means that the abstract class inherited all the methods of the interface. 当我们实现抽象类的接口时,它意味着抽象类继承了该接口的所有方法。 As, it is not important to implement all the method in abstract class however it comes to abstract class (by inheritance too), so the abstract class can left some of the method in interface without implementation here. 因为,在抽象类中实现所有方法并不重要,但是涉及抽象类(也是通过继承),因此抽象类可以将某些方法留在接口中,而无需在此处实现。 But, when this abstract class will inherited by some concrete class, they must have to implements all those unimplemented method there in abstract class. 但是,当此抽象类将由某个具体类继承时,它们必须必须在抽象类中实现所有那些未实现的方法。

Given the interface: 给定接口:

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

This is how Java actually sees it: Java实际上是这样看的:

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

So you can leave some (or all) of these abstract methods unimplemented, just as you would do in the case of abstract classes extending another abstract class. 因此,您可以不执行某些(或全部)这些abstract方法,就像在abstract类扩展另一个abstract类的情况下一样。

When you implement an interface , the rule that all interface methods must be implemented in the derived class , applies only to concrete class implementation (ie, which isn't abstract itself). implement interface ,必须在派生class实现所有interface方法的规则仅适用于具体的class实现(即,它本身不是abstract )。

If you indeed plan on creating an abstract class out of it, then there is no rule that says you've to implement all the interface methods (note that in such a case it is mandatory to declare the derived class as abstract ) 如果确实打算用它创建一个abstract class ,那么就没有规则说必须implement所有interface方法(请注意,在这种情况下,必须将派生class声明为abstract )。

When an Abstract Class Implements an Interface 当抽象类实现接口时

In the section on Interfaces, it was noted that a class that implements an interface must implement all of the interface's methods. 在“接口”部分中,指出了实现接口的类必须实现接口的所有方法。 It is possible, however, to define a class that does not implement all of the interface's methods, provided that the class is declared to be abstract. 但是,可以定义一个不实现所有接口方法的类,前提是该类被声明为抽象的。 For example, 例如,

abstract class X implements Y {   
    // implements all but one method of Y
}

class XX extends X {   
    // implements the remaining method in Y 
} 

In this case, class X must be abstract because it does not fully implement Y, but class XX does, in fact, implement Y. 在这种情况下,类X必须是抽象的,因为它不能完全实现Y,但是实际上,类XX可以实现Y。

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

Abstract classes are not required to implement the methods. 不需要抽象类即可实现这些方法。 So even though it implements an interface, the abstract methods of the interface can remain abstract. 因此,即使它实现了一个接口,该接口的抽象方法也可以保持抽象。 If you try to implement an interface in a concrete class (ie not abstract) and you do not implement the abstract methods the compiler will tell you: Either implement the abstract methods or declare the class as abstract. 如果您尝试在具体类中实现接口(即非抽象)并且未实现抽象方法,则编译器会告诉您:要么实现抽象方法,要么将类声明为抽象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM