为什么一个父类要实现接口方法,这些方法本应该由子类实现?

4

这里是一个父类

public class Parent {
    public void f() {

    }
}

这是一个简单的界面。
public interface If {
    public void f();
}

这是一个子类

public class Child extends Parent implements If{}

我的问题是: 虽然声称要实现接口If的是Child,但是接口方法是在Parent中实现的。为什么允许这样做?


因为您可以自由地命名您编写的方法,所以它不实现接口,只是有一个名为f的方法。 - SomeJavaGuy
1
这是一个奇怪的问题。为什么我们要禁止这个呢? - Holger
3
接口方法被实现在父类中。- 不,这里没有发生这种情况。 - Smutje
1
Parent 没有实现 任何 接口。 - Sva.Mu
3个回答

9
为什么这是被允许的?
因为Child满足合同。Child通过实现If所做的合同是提供一个公共的f函数,它不接受任何参数并且没有返回值。它做到了。它是如何做到的,在这种情况下是通过从超类继承的,这是无关紧要的。合同得到满足,这是唯一重要的。
接口方法在Parent中被实现了吗?
并不是,它只是恰好有f方法。如果你执行If inst = new Parent(),你会得到编译错误,因为Parent没有说它实现了If(它上面没有implements If); 实现If不是其合同的一部分。另一方面,Child确实提供了该合同,因此If inst = new Child()可以正常工作。
顺便说一下,你可能不会故意这样做,尽管这样做可能没有问题。但是,如果你想使用的超类恰好符合你想要实现的接口中的某个方法,那么这种情况可能会发生。
当发生这种情况时,你有三个选择:
  1. Do nothing and let Parent's method directly implement the interface method.

  2. Override Parent's method even though you're not going to do anything differently, e.g.:

    @Override
    public void f() {
        super.f();
    }
    

    ...which really doesn't accomplish anything unless you have code you want to run prior to or after calling Parent's f.

  3. Override f and implement it yourself, ignoring Parent's version. But that only makes sense if Parent's f does something completely different from the interface method's f — in which case, you shouldn't be subclassing Parent in the first place, because if you reimplement f in terms of the interface's behavior, your f won't satisfy the Parent#f contract anymore (in terms of its behavior) and you'll break the "is a" rule for subclassing.

所以说,如果这一切是自然而然发生的,那么选项1就非常合理。但你可能不会有意地设置它。


只是补充一下,这种方法在逻辑上并不正确——如果以后有人更改了Parent的实现并从中删除了方法f(或者更改了其签名等),那么Child就不再有效了。 - Sva.Mu
@Sva.Mu:Child已经与Parent紧密绑定,这是子类化的本质。Parent的更改可能会影响Child的方式有很多。 - T.J. Crowder
我并不是说它不是,而是试图指出是Child对接口作出承诺,而不是Parent,因此更合理的做法是直接在Child中实现接口方法,因为没有任何事情会强制Parent去"保持它"。 - Sva.Mu
@Sva.Mu:但请记住,Child 对于 Parent 也有一个“是一个”的承诺。我已经在答案中添加了相关内容。我不认为这种情况曾经在我的 Java 编程中出现过,思考各种选项还是很有趣的。 - T.J. Crowder

2

这是完全合法的,因为当您实现该方法时,它适用于两者。

从类的角度和接口的角度来看,单个实现将同时满足两个目的,没有任何歧义。

除非与它们存在关系,否则无法限制类或接口具有相同的方法签名,但在这种情况下不会有问题。


0
接口的主要目的是列出一组方法,这些方法可以在实现接口的类的任何对象上调用。
通过声明一个类实现一个接口,您声明该方法集可以在您的类上调用。
一旦这种情况发生(例如在您的示例中),就没有问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接