0
package main;

class F {
    void f() {
        System.out.print("F.f() ");
        this.g();
    }

    void g() {
        System.out.print("F.g() ");
    }
}

class Fbis extends F {
    void f() {
        System.out.print("Fbis.f() ");
        this.g();
    }

    void g() {
        System.out.print("Fbis.g() ");
        super.f();
    }
}

public class Main {
    public static void main(String[] args) {
        F f = new Fbis();
        ((F) f).f();
    }
}

嗨,我想了解为什么永远不会调用 F 类中的 g() 函数。此代码编译并运行,但会导致显示如下的无限循环:

Fbis.f() Fbis.g() F.f() Fbis.g() F.f() Fbis.g() F.f() Fbis.g() F.f() Fbis.g() F.f() Fbis.g() F.f() Fbis.g() F.f() Fbis.g() F.f() ...

所以会发生什么,就是Fbis.f调用,调用Fbis.g,调用,F.f而不是调用F.gF.f调用Fbis.g

4

6 回答 6

9

基本上,这就是继承的工作方式。该类Fbis覆盖该g()方法,因此对于任何Fbis调用实例都g()将运行该类中的代码Fbis,即使它是从F类本身内部调用的。

这通常是可取的行为。例如,想象一个delete()方法。在父类中,当您的应用程序删除对象时,这会进行一些清理。在子类中,它会针对这个孩子进行额外的清理。您会希望在每次调用时都进行额外的清理delete(),即使这是在父类中进行的。

于 2012-10-24T12:57:52.033 回答
0

Ff 但不是调用 Fg,而是 Ff 调用 Fbis.g。

你的代码说

void f(){System.out.print("F.f() ");this.g();}

这意味着F.f()应该调用g();这个类实现的类。

如果你想让 Fbis.g 调用 Fg 你会写

void g(){System.out.print("Fbis.g() "); super.g();}
于 2012-10-24T12:59:08.180 回答
0

当你重写一个方法时,总是使用被重写的版本,不管你从哪里调用它。

当你this.g()在基类中做,并且当前对象属于一个子类时,你g()在子类中调用。

当您在基类中有任何从基类调用的方法,并且您不想让它们被派生类替换时,您应该将该方法设为私有且最终的。

于 2012-10-24T12:59:20.627 回答
0

你的Fbis类覆盖了方法g()。如果您创建一个新对象,Fbis则唯一命名的方法g是在Fbis. 即使您从继承的方法中调用它,它仍然是唯一的方法。否则,如果您创建一个指向该对象的对象,那么如果它在超类中使用也是如此Fbisthis

于 2012-10-24T13:00:16.150 回答
0

方法 Fg() 不再存在于 Fbis 中!

因为您正在“覆盖” Fbis 中的 g() 方法。了解仅使用“super.g”将保留覆盖。

于 2012-10-24T13:01:08.617 回答
0
class F {
    void f() {
        System.out.print("F.f() ");
        this.g(); //<----- This line calls Fbis.g() not F.g() 
                  // because this is the instance of Fbis
    }
于 2012-10-24T13:24:05.527 回答