【问题标题】:Require child classes to call super.doSomething() if overrides it?如果覆盖它,需要子类调用 super.doSomething() 吗?
【发布时间】:2012-01-24 05:37:06
【问题描述】:

我有一个名为 Vehicle 的抽象类:

public abstract class Vehicle {

    public void run() {
        addToRunningVehicleList();
    }

}

如果override run 方法,我希望extends Vehicle 的每个类都必须调用super.run()。例如:

public class Car {

    @Override
    public void run() { // Error here because does not call super.run()
        carRunningAnimation();
    }

}

在 OOP 概念或 Java/C# 中是否可能?

编辑:在 Petar Ivanov 之后,我有以下代码:

public abstract class Vehicle {

    public final void run() {
        Log.e("Run", "Add To List");
        runImp();
    }

    public void runImp() {}

}

public class Car extends Vehicle {

    @Override
    public void runImp() {
        Log.e("Run", "Run in Car");
    }

}

但是,这对于公共 API 来说并不是很好。扩展Vehicle时,最终用户必须覆盖runImp,但随后他们必须调用run()方法,所以我必须将runrunImp都公开,这没有更好的办法。

【问题讨论】:

  • 记住你是为谁设计的。如果它是一段内部代码,注释就足够了。如果它是一个公共 API,并且您希望人们继承,那么您需要编写一段文档告诉他们这样做。在 C# 中,您可以使用虚拟和非虚拟方法做一些鬼鬼祟祟的事情,但在 Java 中,如果不使用抽象基类就很难做到这一点。
  • @Spence 你真的了解我的情况。我正在编写公共 API,所以也许 cmets 或文档还不够。不幸的是,我找不到 virtual 的 Java 等效项:(您应该发布您的评论作为答案,并附上一些代码,我会选择您的答案 :)

标签: c# java oop inheritance polymorphism


【解决方案1】:

我会这样做(C#):

public abstract class Vehicle {

    public void Run() {
        //code that will always run
        addToRunningVehicleList();

        //code that can be overriden
        RunImpl();
    }

    protected virtual void RunImpl() { }
}

public class Car : Vehicle {

    protected override void RunImpl() {
        carRunningAnimation();
    }

}

您可以将RunImpl 设置为受保护,以确保它不能在Vehicle 的子类之外调用。

【讨论】:

  • 有没有办法在 Java 中实现这一点?我在 Java 中找不到 virtual 等价。
  • 在 Java 中所有方法都是虚拟的,除非你将它们标记为 final en.wikipedia.org/wiki/Final_(Java)
  • 感谢您提供的非常有趣的事实。但是还是有问题,刚刚编辑了我的问题。
  • 其实你的runImpl是可以保护的。我编辑了我的答案。这样,它在 Vehicle 的子类之外不可用。另请注意,您的 run 方法应该是 final 以避免被覆盖。
  • 你不明白我的目的。 Vehicle 类用于 PUBLIC,最终用户可以创建类似 Car 之类的东西。总之,这就是我需要的:提供Vehicle 类,任何人都可以扩展它并使用run 默认方法。或者他们可以根据需要覆盖它,但它必须调用 super.run() 方法。
【解决方案2】:

如果除了子类的实现之外,您还需要运行某些代码,也许您需要将其拆分为多个方法:

(C# 示例)

public abstract class Vehicle
{
    public void Run()
    {
        // Code that always runs before...

        RunCore();

        // Code that always runs after...
    }

    protected virtual void RunCore()
    {
    }
}

【讨论】:

    【解决方案3】:

    记住你是为谁设计的。如果它是一段内部代码,注释就足够了。如果它是一个公共 API,并且您希望人们继承,那么您需要编写一段文档告诉他们这样做。

    在 C# 中,您可以使用虚拟和非虚拟方法做一些鬼鬼祟祟的事情,但在 Java 中,由于所有继承都是虚拟的,因此在不使用抽象基类的情况下实施这一点要困难得多。

    使用 ABT 可能会限制您提供进一步继承和强制修改其他代码的能力。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-14
      • 1970-01-01
      • 1970-01-01
      • 2010-10-20
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多