【问题标题】:Android - how to force child to override parent method that has codeAndroid - 如何强制孩子覆盖有代码的父方法
【发布时间】: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 类,以便它有一个方法可以做某事,但要求每个孩子都重写它?
  • 如何强制子级(必须重写该方法)也调用父级的方法?

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

【问题讨论】:

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

标签: java android inheritance methods


【解决方案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(),并且您知道父母所做的事情每次都会发生

【讨论】:

    猜你喜欢
    • 2018-03-18
    • 2017-11-18
    • 1970-01-01
    • 2011-05-21
    • 1970-01-01
    • 2014-04-14
    • 2018-02-17
    • 2011-05-19
    • 1970-01-01
    相关资源
    最近更新 更多