当前位置:  开发笔记 > 编程语言 > 正文

如果内部类扩展外部类,内部类的不同成员行为?

如何解决《如果内部类扩展外部类,内部类的不同成员行为?》经验,为你挑选了3个好方法。

今天我偶然发现了一些奇怪的内部(非静态)类行为.

如果我有以下课程......

class B {
    String val = "old";

    void run(){
        val = "new";
        System.out.println(val);        // outputs: new
        new InnerB().printVal();        // outputs: new
    }

    private class InnerB {
        void printVal(){ System.out.println(val); }
    }
}

new B().run();

......一切似乎都很清楚.InnerB的实例属于B的实例,因此如果它应该输出val,则打印已经替换的值'new'.

但是如果内部类扩展了外部类,则这不起作用.

class B {
    String val = "old";

    void run(){
        val = "new";
        System.out.println(val);        // outputs: new
        new InnerB().printVal();        // outputs: new
        new InheritedB().printVal();    // outputs: old new
    }

    private class InnerB {
        void printVal(){ System.out.println(val); }
    }

    private class InheritedB extends B{
        void printVal(){ System.out.println(val + " "+ B.this.val); }
    }
}

new B().run(); // outputs: new new old!

如果我查看构造函数,我还会看到如果创建了InheritedB的实例,将创建一个新的B实例.

我发现这很奇怪......有人可以解释为什么会有这种差异吗?



1> Jon Skeet..:

这一行:

new InheritedB().printVal();   

创建一个新实例InheritedB,其实例是B(其中val是"new")的现有实例.但此时有两个 val变量:

现有实例中的一个 B

实例中的一个InheritedB,具有单独的val字段

第二个变量的值是"old"因为它实际上是字段的默认值.

本声明InheritedB:

System.out.println(val + " "+ B.this.val);

打印出val继承自的值B,后跟val"包含实例"中的值.

可以更简单地认为它被重构为:

public class B
{
    String val = "old";
}

public class InheritedB extends B {
    B other;

    public InheritedB(B other)
    {
        this.other = other;
    }

    void printVal() {
        System.out.println(val + " "+ other.val);
    }
}

然后你基本上运行:

B original = new B();
original.val = "new":
InheritedB inherited = new InheritedB(original);
inherited.printVal();

希望你能完全按照那里发生的事情.编译器大致将原始代码执行到该代码中.



2> SLaks..:

valin InheritedB指的val是它的基类(super.val),因为那是它的一部分this.

如果不从外部类继承,val则从外部类(B.this.scope)引用作用域.但是,由于您继承,this因此范围更近,因此隐藏了外部范围.

既然你从未打过run() 内心this,那this.val还是old.


如果我查看构造函数,我还会看到如果创建了InheritedB的实例,将创建一个新的B实例.

是; 创建派生类将始终创建其基类的实例.无法从现有实例继承.



3> Arnaud..:

因为InheritedB extends B,创建一个InheritedB实例会授予它一个val属性,默认情况下,该属性对于任何新的 B类或子类实例都是"旧的" .

在这里,InheritedB 打印自己的 val属性,而不是封闭的B实例之一.

推荐阅读
linjiabin43
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有