[英]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
}
}
正如你所看到的,第二次分配Parent
的i
不会改变第一(无论你设置的i
-在构造函数或其他地方)。 这是因为:
i
是一个实例变量。 每个实例都为其自己的int i
分配了内存。 这意味着引用p1
和p2
拥有2个不同的 int i
s-更改一个不会更改另一个。
但是 ,如果您声明static int i
,则将使i
成为一个类变量,该变量在该类的所有实例之间共享。 在这种情况下,第一个分配将被第二个覆盖。
如果您对手续感兴趣,那么JLS中有很多有关此方面的内容...
编辑:解决评论
就我而言,当我创建一个装饰器对象时,由于它是抽象的,因此无法实例化其超类。 所以我还不明白为什么每个装饰器都有自己的组件。
这里是JLS的技术知识。
您说对了,我们不能使用new MyAbstClass()
实例化abstract
类。 JLS 8.1.1.1。 abstract
类:
如果尝试使用类实例创建表达式(第15.9.1节)创建
abstract
类的实例,则会出现编译时错误。
但:
可以实例化本身不是
abstract
的abstract
类的子类,从而导致执行该abstract
类的构造函数,并因此执行该类的实例变量的字段初始化器。
实例化DecoratorA
和DecoratorB
,将调用AbstractComponent
的构造函数,并初始化实例字段component
。 因此,实际上,您确实有2个component
字段。
它们是不同的对象,因此完全不应覆盖对c的组件分配。
您具有:对象b,其成分为d1,以及对象d1,其成分为c
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.