Java - 子类调用supers构造函数,它调用子类方法而不是自己的 [英] Java - Subclass calls supers constructor which calls subclass method instead of its own

查看:349
本文介绍了Java - 子类调用supers构造函数,它调用子类方法而不是自己的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将从一个代码示例开始:

I'll start with a code example:

class A {
    public A() {
        f(); //When accessed through super() call this does not call A.f() as I had expected.
    }

    public void f() {} //I expect this to be called from the constructor.
}

class B extends A {
    private Object o;

    public B() {
        super();
        o = new Object(); //Note, created after super() call.
    }

    @Override
    public void f() {
        //Anything that access o.
        o.hashCode(); //Throws NullPointerException.
        super.f();
    }
}

public class Init {
    public static void main(String[] args) {
        B b = new B();
    }
}

此程式会引发 NullPointerException 。当对象b进入其超类 A 的构造函数并调用重载的方法 f()由类B Bf()被调用,而不是 Af()这是我预期的。

This program throws a NullPointerException. When the object b enters the constructor of its superclass A and makes a call to the method f() which is overridden by the class B B.f() is called, instead of A.f() which I would have expected.

我认为一个超类不应该知道它是否是子类化的,但肯定这可以被一个类用来告诉它是否被子类化?这是什么原因?如果我真的想要 A.f()而不是 B.f(),是否有任何解决方法?

I thought a superclass wasn't supposed to know if it was subclassed or not but surely this can be used by a class to tell if it's been subclassed or not? What's the reason behind this? Is there any workaround if I really want A.f() to be called instead of B.f()?

提前感谢。

后续问题:

感谢您的答案。我现在明白为什么是这样,但这里是一个后续问题。也许我错了,但子类型的原则是超类型不应该知道它是子类型。这个机制让一个类知道它是否被子类化。考虑这个代码示例:

Thanks for the answers. I now understand why it is like it is, but here's a follow up question. Perhaps I'm mistaken but a principle of subtyping is that the supertype should not know that it's been subtyped. This "mechanism" lets a class know if it's been subclassed or not. Consider this code example:

class A {
    private boolean isSubclassed = true;

    public A() {
        f(); //A.f() unsets the isSubclassed flag, B.f() does not.
        if(this.isSubclassed) {
            System.out.println("I'm subclassed.");
        } else {
            System.out.println("I'm not subclassed.");
        }
    }

    public void f() {
        this.isSubclassed = false;
    }
}

class B extends A {
    public B() {
        super();
    }

    @Override
    public void f() {}
}

public class Init {
    public static void main(String[] args) {
        new B(); //Subclass.
        new A();
    }
}

此程序的输出为:

I'm subclassed.
I'm not subclassed.

这里 A 知道它已经被子类化。这是谁不知道谁,但没有关系。这是怎么解释的?我误入歧途?发生 NullPointerException 的原因是当你构造一个B的实例时,会发生这种情况:

Here A knows it's been subclassed. It's unkown by whom but that doesn't matter. How is this explained? Am I misinformed?

推荐答案

父构造函数(在A中)被调用。这个构造函数调用 f()方法,但由于对象的实际类型是B,重写的 f()调用B中的方法。

The NullPointerException occurs because when you construct an instance of B, the parent constructor (in A) is invoked. This constructor calls the f() method but since the actual type of the object is B, the overridden f() method in B is invoked.

@Override
public void f() {
    //Anything that access o.
    o.hashCode(); //Throws NullPointerException as o has not been initialised yet
    super.f();
}

这里的课程永远不会在构造函数中调用方法可以被子类覆盖。

这篇关于Java - 子类调用supers构造函数,它调用子类方法而不是自己的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆