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

发布于 2024-07-07 22:32:59 字数 374 浏览 10 评论 0原文

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

例如,给定接口:

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

以下抽象类可以顺利编译,没有警告或错误:

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

你能解释一下为什么吗?

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 (i.e. neither an abstract declaration or an actual implementation is present), but the compiler does not complain.

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

¢好甜 2024-07-14 22:32:59

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

按照您的示例代码,尝试创建 AbstractThing 的子类而不实现 m2 方法,并查看编译器给出的错误。 它将迫使您实施此方法。

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. It will force you to implement this method.

红尘作伴 2024-07-14 22:32:59

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

更新:有趣的是,我发现 C# 强制将此作为编译错误。 在这种情况下,您被迫复制方法签名并在抽象基类中添加“abstract public”前缀。(每天都有新东西:)

Perfectly fine.
You can't instantiate abstract classes.. but abstract classes can be used to house common implementations for m1() and m3().
So if m2() implementation is different for each implementation but m1 and m3 are not. You could create different concrete IAnything implementations with just the different m2 implementation and derive from AbstractThing -- honoring the DRY principle. 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. 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:)

一曲琵琶半遮面シ 2024-07-14 22:32:59

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

正如您所看到的,这也可以完美编译。 原因很简单,就像抽象类一样,接口不能被实例化。 因此,不需要明确提及其“父级”的方法。 但是,所有父方法签名都隐式成为扩展接口或实现抽象类的一部分。 因此,一旦一个适当的类(可以实例化的类)扩展了上述内容,就需要确保实现每个抽象方法。

希望能有所帮助……真主阿拉!

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 !

浪漫人生路 2024-07-14 22:32:59

给定接口:

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 的情况下所做的那样> 扩展另一个抽象类的类。

当您实现一个接口时,所有接口方法必须在派生中实现的规则仅适用到具体的class实现(即,它不是abstract本身)。

如果您确实计划从中创建一个抽象类,那么没有规则要求您必须实现所有接口方法(请注意,在这种情况下,必须将派生类声明为抽象)

Given the interface:

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

This is how Java actually sees it:

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.

When you implement an interface, the rule that all interface methods must be implemented in the derived class, applies only to concrete class implementation (i.e., which isn't abstract itself).

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)

傲娇萝莉攻 2024-07-14 22:32:59

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

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.

娇纵 2024-07-14 22:32:59

当抽象类实现接口时

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

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

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.

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

赴月观长安 2024-07-14 22:32:59

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

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 (i.e. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文