摘要中的私有引用 class
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
吗?还是我创建的每个装饰器都有某种私有引用的副本?我找不到解决方案,因为这个引用是私有的,不能被子类继承。
它们是不同的对象,因此根本不应该覆盖对 c 的组件分配。
你有:
对象 b,其组件是 d1,和
对象 d1,其组件为 c
My question is: shouldn't DecoratorB
constructor overwrite the past assignment of c
to 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
. 分配了内存
- 当一个class被实例化时,它所有的超级class层级也被实例化。
这意味着引用 p1
和 p2
保持 2 不同 int i
s - 改变一个不会改变另一个。
但是,如果你声明static int i
,那会使i
成为class 变量,它在 class 的所有实例之间共享。在这种情况下,第一个赋值将被第二个赋值覆盖。
如果您对手续感兴趣,JLS 中有很多关于此的内容...
编辑: 处理评论
In my case, when I create a decorator object, its superclass cannot be instantiated, because it's abstract. So I can't understand yet why every decorator has its own component.
这里是 JLS 技术细节。
你说得对,我们不能用 new MyAbstClass()
实例化 abstract
class。 JLS 8.1.1.1。 abstract
类:
It is a compile-time error if an attempt is made to create an instance of an abstract
class using a class instance creation expression (§15.9.1).
但是:
A subclass of an abstract
class that is not itself abstract
may be instantiated, resulting in the execution of a constructor for the abstract
class and, therefore, the execution of the field initializers for instance variables of that class.
当您实例化 DecoratorA
和 DecoratorB
时,将调用 AbstractComponent
的构造函数并初始化实例字段 component
。所以实际上,您确实有 2 个 component
字段。
我有这段装饰器模式的代码:
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
吗?还是我创建的每个装饰器都有某种私有引用的副本?我找不到解决方案,因为这个引用是私有的,不能被子类继承。
它们是不同的对象,因此根本不应该覆盖对 c 的组件分配。
你有: 对象 b,其组件是 d1,和 对象 d1,其组件为 c
My question is: shouldn't
DecoratorB
constructor overwrite the past assignment ofc
toComponent
?'
没有。让我们看一个具有完全相同行为的稍微简单的案例:
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
. 分配了内存
- 当一个class被实例化时,它所有的超级class层级也被实例化。
这意味着引用 p1
和 p2
保持 2 不同 int i
s - 改变一个不会改变另一个。
但是,如果你声明static int i
,那会使i
成为class 变量,它在 class 的所有实例之间共享。在这种情况下,第一个赋值将被第二个赋值覆盖。
如果您对手续感兴趣,JLS 中有很多关于此的内容...
编辑: 处理评论
In my case, when I create a decorator object, its superclass cannot be instantiated, because it's abstract. So I can't understand yet why every decorator has its own component.
这里是 JLS 技术细节。
你说得对,我们不能用 new MyAbstClass()
实例化 abstract
class。 JLS 8.1.1.1。 abstract
类:
It is a compile-time error if an attempt is made to create an instance of an
abstract
class using a class instance creation expression (§15.9.1).
但是:
A subclass of an
abstract
class that is not itselfabstract
may be instantiated, resulting in the execution of a constructor for theabstract
class and, therefore, the execution of the field initializers for instance variables of that class.
当您实例化 DecoratorA
和 DecoratorB
时,将调用 AbstractComponent
的构造函数并初始化实例字段 component
。所以实际上,您确实有 2 个 component
字段。