繁体   English   中英

抽象类中的私有引用

[英]Private reference in abstract class

我有这段装饰器模式代码:

public interface AbstractComponent {

    public void operation();
}


public class Component implements AbstractComponent {

    public void operation() {
        // do something
    }
}


public abstract class AbstractDecorator implements AbstractComponent {

    private AbstractComponent component;

    public AbstractDecorator(AbstractComponent ac) {
        component=ac;
    }

    public void operation() {
        component.operation();
    }
}


public class DecoratorA extends AbstractDecorator {

    public DecoratorA (AbstractComponent ac) {
        super(ac);
    }

    public void addedOperation() {
        // adds features to Component
    }

    public void operation() {
        addedOperation();
        super.operation();
    }
}


public class DecoratorB extends AbstractDecorator {

    public DecoratorB (AbstractComponent ac) {
        super(ac);
    }

    public void addedOperation() {
        // adds features to Component
    }

    public void operation() {
        addedOperation();
        super.operation();
    }
}


public class Tester {

    public static void main(String args[]) {
        AbstractComponent c = new Component();
        AbstractComponent d1 = new DecoratorA(c);
        AbstractComponent d2 = new DecoratorB(d1);
        d2.operation();
    }
}

创建DecoratorA ,其构造函数调用将引用c分配给component的超类构造函数。 创建DecoratorB ,其构造函数调用将引用d1分配给component的同一超类构造函数。

我的问题是: DecoratorB构造函数不应该覆盖c过去对component赋值吗? 还是为我创建的每个装饰器提供某种私有引用的副本? 我找不到解决方案,因为此引用是私有的,不能被子类继承。

我的问题是: DecoratorB构造函数是否不应该覆盖c过去对Component赋值?

否。让我们看一个行为完全相同的简单案例:

class Parent {

    int i;
}

class ChildA extends Parent {}
class ChildB extends Parent {}

public class Main {

    public static void main(String[] args) {

        Parent p1 = new ChildA();
        Parent p2 = new ChildB();
        p1.i = 3;
        p2.i = 4;
        System.out.println(p1.i); // Output: 3
    }
}

正如你所看到的,第二次分配Parenti不会改变第一(无论你设置的i -在构造函数或其他地方)。 这是因为:

  1. i是一个实例变量。 每个实例都为其自己的int i分配了内存。
  2. 当实例化一个类时,其所有超类层次结构也会被实例化。

这意味着引用p1p2拥有2个不同的 int i s-更改一个不会更改另一个。

但是 ,如果您声明static int i ,则将使i成为一个变量,该变量在该类的所有实例之间共享。 在这种情况下,第一个分配将被第二个覆盖。

如果您对手续感兴趣,那么JLS中有很多有关此方面的内容...

编辑:解决评论

就我而言,当我创建一个装饰器对象时,由于它是抽象的,因此无法实例化其超类。 所以我还不明白为什么每个装饰器都有自己的组件。

这里是JLS的技术知识。

您说对了,我们不能使用new MyAbstClass()实例化abstract类。 JLS 8.1.1.1。 abstract类:

如果尝试使用类实例创建表达式(第15.9.1节)创建abstract类的实例,则会出现编译时错误。

但:

可以实例化本身不是abstractabstract类的子类,从而导致执行该abstract类的构造函数,并因此执行该类的实例变量的字段初始化器。

实例化DecoratorADecoratorB ,将调用AbstractComponent的构造函数,并初始化实例字段component 因此,实际上,您确实有2个component字段。

它们是不同的对象,因此完全不应覆盖对c的组件分配。

您具有:对象b,其成分为d1,以及对象d1,其成分为c

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM