覆盖子类类型的变量

时间:2019-01-23 16:57:30

标签: java oop inheritance

我有一个带有侦听器接口的类。我想用侦听器接口作为子类类型创建一个子类。例如:

interface OnSadListener {
    void imSad();
}

interface OnCryingListener extends OnSadListener {
    void imCrying();
}

class Person {
    OnSadListener listener;

    void setListener(OnSadListener listener){
        this.listener = listener;
    }
}

class Baby extends Person {
    OnCryingListener listener; // I want it to override the original one in Person

    void cry(){
        listener.imSad();
        listener.imCrying();
    }
}

void doIt(){
    Baby michael = new Baby();

    michael.setListener(new OnCryingListener() {
        @Override void imSad(){
            System.out.print("I'm sad");
        }

        @Override void imCrying(){
            System.out.print("Wahhhhhh!");
        }
    });

    michael.cry(); // the imCrying funtion is empty (setListener setted Person's listener and not Baby's)
}

我知道Baby.setListener(new OnCryingListener(){...});会起作用,因为OnCryingListener是OnSadListener的子类。但是那样我将无法调用imCrying(),否则它将为空。

OnCryingListener listener是否可以“替代” Person的{​​{1}}?

2 个答案:

答案 0 :(得分:0)

您需要重写setListener(OnSadListener)类中的Baby方法,因为您从未设置侦听器。

class Baby extends Person {
    OnCryingListener listener;

    @Override
    void setListener(OnSadListener listener) {
        this.listener = (OnCryingListener) listener;
    }

    void cry() {
        listener.imSad();
        listener.imCrying();
    }
}

下面是一个更完整的示例...

class Person {
    protected OnSadListener listener; // Make it protected or add accessor/mutators

    void setListener(OnSadListener listener) {
        this.listener = listener;
    }
}

通过保护listener,可以重用Person类的OnSadListener。您只需要将侦听器强制转换为OnCryingListener即可调用imCrying()方法。

class Baby extends Person {
    @Override
    void setListener(OnSadListener listener) {
        this.listener = (OnCryingListener) listener;
    }

    void cry() {
        listener.imSad();
        ((OnCryingListener) listener).imCrying(); // Cast here
    }
}

更新

如果要使用泛型,则可以省去强制转换。

public class Person <T extends OnSadListener> {
    protected T listener;

    public void setListener(T listener) {
        this.listener = listener;
    }
}

现在您可以告诉Baby正在处理哪种类型的侦听器。

public class Baby extends Person<OnCryingListener> {
    @Override
    public void setListener(OnCryingListener listener) {
        this.listener = (OnCryingListener) listener;
    }

    public void cry() {
        listener.imSad();
        listener.imCrying(); // No need to cast
    }
}

答案 1 :(得分:0)

在Java中,字段不是“覆盖”的。仅方法被覆盖。

由于您假定字段被覆盖,因此在此示例中,您期望listener对象中仅存在一个Baby字段。并且您希望在调用michael.setListener()时设置单个字段。

但是实际上,Baby对象中有2个字段。调用michael.setListener()时,只会设置Person类中声明的字段。