gpt4 book ai didi

java - 抽象类中的私有(private)引用

转载 作者:行者123 更新时间:2023-12-01 10:23:26 29 4
gpt4 key购买 nike

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

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 时,其构造函数会调用父类(super class)构造函数,将引用c 分配给component。创建 DecoratorB 时,其构造函数会调用相同的父类(super class)构造函数,将引用 d1 分配给 component

我的问题是:DecoratorB 构造函数不应该覆盖 ccomponent 的过去赋值吗?或者我创建的每个装饰器是否都有某种私有(private)引用的副本?我找不到解决方案,因为该引用是私有(private)的,不能被子类继承。

最佳答案

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
}
}

如您所见,Parenti 的第二次赋值不会更改第一个赋值(无论您在何处设置 i -在构造函数或其他任何地方)。这是因为:

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

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

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

如果您对手续感兴趣,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 类。 JLS 8.1.1.1。 抽象类:

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.

当您实例化 DecoratorADecoratorB 时,将调用 AbstractComponent 的构造函数,并调用实例字段 component已初始化。所以事实上,您确实有 2 个 component 字段。

关于java - 抽象类中的私有(private)引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35455368/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com