如何从继承类调用抽象类中的抽象方法

6
我想从一个被继承类调用的抽象类中调用一个方法。
抽象类:
public abstract class Abstract {
    protected void updateMotionY(float deltaTime) {
        System.out.println("Abstrcat updateMotionY");
    }
    public void update(float deltaTime) {
        this.updateMotionY(deltaTime);
    }
}

继承类:
public class Obj extends Abstract {
    @Override
    protected void updateMotionY(float deltaTime) {
        System.out.println("updateMotionY");
        super.updateMotionY(deltaTime);
    }
    @Override
    public void update(float deltaTime) {
        super.update(deltaTime);
    }
}

主方法类:
public static void main(String[] args) {
    (new Obj()).update(10.0f);
}

每当我在主类中尝试调用`new Obj().update()`方法时,它会打印出"updateMotionY"和"Abstract updateMotionY"。我只想得到"Abstract updateMotionY"。
有人能告诉我如何解决这个问题吗?

2
“它会抛出:updateMotionY和Abstrcat updateMotionY”这句话是错误的。异常(你“抛出”的东西)不是这个样子的。你是指它会输出这些信息吗?如果是,那为什么会让你感到惊讶呢?毕竟是你告诉程序要输出这些信息的。” - T.J. Crowder
2
Obj类中update()的覆盖是多余的。 - CloudPotato
它在控制台中显示updateMotionY和Abstrcat updateMotionY。两种方法都被调用。我想只调用抽象方法。 - Amadeus
1
使用正确的术语:“throws”指的是异常或错误。你的意思是“打印”或“显示”。 - RealSkeptic
感谢您的建议,我已经修正了线程。 - Amadeus
4个回答

4

我认为你对 abstract 的使用方法完全错误了。你的 base 类应该像这样:

public abstract class Abstract {
  protected abstract void updateMotionY(float deltaTime);

  public final void update(float deltaTime) {
    this.updateMotionY(deltaTime);
  }
}

注:

  • 在抽象方法中放置print“is abstract”没有意义。Java语言有一个关键字来表达这个事实。
  • 子类应该关于实现抽象方法(可能以不同的方式)。您绝对不希望子类更改基类的其他方法的实现。您的基类定义了一个合同 - 子类应该遵守该合同(如Liskov替换原则所述)。

换句话说:只将公共部分放在基类中,并确保您必须在其中具有必要的abstract方法。但是避免多次实现方法。这只会导致混乱和奇怪的错误。


是的。我认为这是他应该使用的结构。 - Michael

3

(new Obj()).update(10.0f) 调用了 Obj::update 方法,该方法又调用了 Abstract::update 方法,而这个方法又调用了 this.updateMotionY。由于 thisObj 类的一个实例,因此它会调用 Obj::updateMotionY 方法。

这会输出 "updateMotionY"。

随后,它又调用了 super.updateMotionY(deltaTime),即 Abstract::updateMotionY 方法。

这会输出 "Abstract updateMotionY"。

这就是调用层级的末端,然后一切都会解开。


你的困惑根本上似乎源于 Abstract 类中的 this.updateMotionY(deltaTime); 解析到了 Obj 类中的 updateMotionY 方法。这基本上就是多态的全部意义


你可以做的一件事是添加一个私有方法(以便不能被覆盖),其中包含实际的实现,并将其推迟:

public abstract class Abstract {
    private void motionY(float dt)
    {
        System.out.println("Abstrcat updateMotionY");
    }

    protected void updateMotionY(float deltaTime) {
        motionY(deltaTime);
    }
    public void update(float deltaTime) {
        motionY(deltaTime);
    }
}

但是如果我想调用Abstract::update而不包括Obj::update,该如何操作呢?如果我删除这个子句,什么也不会改变。 - Amadeus
编辑了我的答案,并给出了一种可能的实现方法。 - Michael
1
很好的解释。在我的答案中,我有一些其他的想法。 - GhostCat

0

如果你只想执行抽象超类的方法,那么简单的解决方案就是在你的Obj类中调用super.updateMotionY而不是super.update

public class Obj extends Abstract {
    @Override
    protected void updateMotionY(float deltaTime) {
        System.out.println("updateMotionY: ");
        super.updateMotionY(deltaTime);
    }
    @Override
    public void update(float deltaTime) {
        super.updateMotionY(deltaTime);
    }
}

0

你不能创建抽象类的实例,所以你正在创建 Obj 类的实例。既然你的要求只是调用抽象类的方法,那么为什么要重写 updateMotionY 方法呢?

根据你的需求,这是你需要做的:

抽象类:
public abstract class Abstract {
    protected void updateMotionY(float deltaTime) {
        System.out.println("Abstrcat updateMotionY");
    }
    public void update(float deltaTime) {
        this.updateMotionY(deltaTime);
    }
}

继承类:

public class Obj extends Abstract{
    /*@Override
    protected void updateMotionY(float deltaTime) {
        System.out.println("updateMotionY");
        super.updateMotionY(deltaTime);
    }*/
    @Override
    public void update(float deltaTime) {
        super.update(deltaTime);
    }
}

我已经注释了被覆盖的代码,这将为您提供所需的结果。 此外,https://stackoverflow.com/users/8466177/steven-laan 给出的答案也可以使用。


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