【问题标题】:Java: recursion within main-class calls subclass-method instead of its own methodJava:主类中的递归调用子类方法而不是它自己的方法
【发布时间】:2015-04-21 06:52:33
【问题描述】:

例子:

class MainClass {
    public doIt() {
        ...
        else doIt();
    }
}

class SubClass extends MainClass {
    @Override
    public doIt() {
        super.doIt();
        ...
    }
}

现在的问题是:

  • 我调用 SubClass.doIt()
  • MainClass.doIt() 被调用
  • MainClass.doIt() 进行递归调用 doIt()
    但是:调用 SubClass.doIt() 而不是 MainClass.doIt()

这是非常奇怪的行为,并且问题被编程了!我试图用 this.doIt() 调用递归,但这没有帮助。 有人有想法吗?

非常感谢您的回答,这个问题已经解决了。

【问题讨论】:

  • 这就是你的多态性。
  • "这是非常奇怪的行为" 不是真的,else doIt()else this.doIt() 相同,但 this 指的是当前实例,并且感谢动态绑定 (多态机制)来自最接近this 的当前类型的类方法的代码被调用。由于与包含doItSubClass 最接近的类是SubClass 本身,因此调用此代码。
  • 这是假定的行为。

标签: java recursion subclass mainclass


【解决方案1】:

这是假定的行为,通过不设置方法final,这意味着它可以是overriden,所以你必须始终考虑到有人可以这样做。对该方法的调用永远不能保证是该级别的方法。

但是,您可以通过使用 (protected) final 方法优雅地解决此问题:

class MainClass {

    protected final void innerDoIt () { //final: so no @Override
        ...
        else innerDoIt();
    }

    public void doIt() {
        innerDoIt();
    }

}

然后:

class SubClass extends MainClass {

    @Override
    public doIt() {
        super.doIt();
        ...
    }
}

final 确保该方法不能被覆盖。所以在那一刻,你有一个合同(保证)innerDoIt 方法确实是你认为的innerDoIt 方法。

因此,如果您不希望调用者被覆盖,只需将其对冲到另一个 final 方法中。通过将其设为protected,该方法也可以由SubClass 调用。

【讨论】:

  • 好吧不知道,奇迹我所有的东西都跑到现在:p - 非常感谢
【解决方案2】:
public class Main {

    public static void main(String[] args) {
        B b = new B();
        b.doIt();
        System.out.println();
        A a = new B();
        a.doIt();
    }


    public static class A{
        boolean check=false;
        public void doIt(){
            System.out.println("A start");
            if(check){

            }
            else{
                check = true;
                doIt();
            }
            System.out.println("A end");
        }
    }
    public static class B extends A{
        @Override
        public void doIt() {
            System.out.println("B start");
            super.doIt();
            System.out.println("B end");
        }
    }
}

在本例中,ba 都是类 B 的实例,因此如您所料,a.doIt() 和 b.doIt() 将输出相同的结果。

B start
A start
B start
A start
A end
B end
A end
B end

B start
A start
B start
A start
A end
B end
A end
B end

当您调用doIt() 时,您隐式调用this.doIt(),而this 是类B 的一个实例。如果不分隔 doIt() 的内容,就没有语法可以做你想做的事(见 CommuSoft 的回答)

【讨论】:

    猜你喜欢
    • 2014-01-22
    • 2016-01-13
    • 2013-12-05
    • 1970-01-01
    • 2014-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-17
    相关资源
    最近更新 更多