Android - 如何强制孩子覆盖有代码的父方法

Posted

技术标签:

【中文标题】Android - 如何强制孩子覆盖有代码的父方法【英文标题】:Android - how to force child to override parent method that has code 【发布时间】:2013-01-06 16:09:46 【问题描述】:

这是场景 -> 假设有 3 个类,我想做一些类似的事情:

public class GameObject 
    public void updateBounds() 
        // do something
    


public abstract class Enemy extends GameObject 
    public abstract void updatePosition() //<-- this will not compile, 
                                    //but this is what i want to do, to force 
                                    //child to override parent method
        updateBounds();
    



public class Minion extends Enemy 
    @Override
    public void updatePosition() 
        super.updatePosition(); // <-- how do i throw an exception if this line
                                // is not called within this method of the
                                // child?
        // now do something extra that only Minion knows how to do
    

您如何设计 Enemy 类,以便它有一个方法可以做某事,但要求每个孩子都重写它? 如何强制子级(必须重写该方法)也调用父级的方法?

这几乎就像 androidActivity 类具有 onCreate、onStart、onResume...等。方法是可选的,但如果你使用它,它会强制你调用 super.它不能是抽象的,因为我希望在调用方法时运行一些代码(仅在父类的方法中)。如果你知道他们是怎么做到的,可以加分吗?

【问题讨论】:

要强制覆盖函数调用其超类,请将此注释添加到超类中的函数:@CallSuper。 Android Studio 会像onCreate 一样给你提醒 【参考方案1】:

怎么样

public abstract class Enemy extends GameObject
    public abstract void updatePositionCommon() 
        //code common to all

        updatePosition();
    
    public abstract void updatePosition() 
        //override this method in children
    


【讨论】:

抽象方法不能有主体。【参考方案2】:

Android Sources 使用一个名为 mCalled 的布尔值,在准抽象方法实现内部设置为 true。在您的情况下,这将在原始 updatePosition() 内部。

那么当你想调用updatePosition()时,通过这个调用它:

private void performUpdatePosition() 
    mCalled = false;
    updatePosition();
    if (!mCalled) throw new SuperNotCalledException();

updatePosition() 看起来像这样

protected void updatePosition() 
    mCalled = true;
    updateBounds();

编辑:

现在想想,android 的做法有点绕。因为对updatePosition() 的所有调用都经过performUpdatePosition(),所以您不再需要在updatePosition() 中包含一些可以被覆盖但不应该被覆盖的代码。

更好的方法是将所需的操作简单地移动到performUpdatePosition()

private void performUpdatePosition() 
    updateBounds();
    updatePosition();


protected void updatePosition() 
    //Do nothing by default

这样被调用者不必担心调用super.updatePosition。如果子类不覆盖该函数,则不会发生任何额外的事情,而如果他们这样做,覆盖将添加到先前的行为。

【讨论】:

嗯...好吧。我希望在java中已经有一个更成熟的解决方案,我只是不知道。但我想这个黑客现在必须做。谢谢!!!投票(几天前)并接受 我已经编辑了这个问题,给出了另一种(更好的)解决这个问题的方法。【参考方案3】:

你如何设计 Enemy 类,使它有一个方法 东西,但要求每个孩子都覆盖它?

为此,您的父类方法需要定义为抽象方法,这是子类知道父类中定义的方法需要在子类中定义的唯一方式。

您如何强制孩子(必须重写该方法)也 调用父类的方法?

如果父类是抽象类,则覆盖方法。

【讨论】:

OP 希望能够在updatePosition() 期间强制执行一些公共代码,并且如果它没有命中公共代码,仍然允许通过抛出异常来覆盖它。【参考方案4】:

也许你可以在类中定义一个基方法,而不是调用子方法

public void updatePosition()

    //do what you need to do before the child does it's stuff
    onUpdatePosition();
    //do what you need to do after the child does it's stuff


protected abstract void onUpdatePosition();

这样,当您调用 updatePosition() 时,孩子必须拥有自己的 onUpdatePosition(),并且您知道父母所做的事情每次都会发生

【讨论】:

以上是关于Android - 如何强制孩子覆盖有代码的父方法的主要内容,如果未能解决你的问题,请参考以下文章

PHP继承的父方法无法访问孩子的私有属性

从 PEM 导入 JWK 时如何覆盖自动计算的孩子

有两个孩子的父 div。即使没有显示另一个孩子,也总是让一个孩子填充父母?

SQL Recursive:获取孩子的父值

如何退出GIT的rebase状态,强制覆盖本地代码

如何使用JQuery在输入中选择其孩子在最后一个不为空的父级的上一个兄弟姐妹