我正在设计一个类层次结构,我以标题的形式遇到了问题,这里是它的一个较小的抽象:
public abstract class A {
private C c;
public A(C c) {
this.c = c;
}
// ...
}
public class B extends A {
private int a;
private int b;
// ...
public B(int a, int b, ... /* and more but no object of C */) {
super(new C(this)); // <-- this is the point, got error:
// can't access `this` .
this.a = a;
this.b = b;
// ...
}
}
public class C {
private A a;
public C(A a) {
this.a = a;
}
}
简而言之:A
需要保留对C
的引用,反之亦然,但是两者都应在其构造函数中完成,并且在构造完这两个字段之后,A a
和C c
不应更改,因此我将它们设置为private
。那么在这种情况下,最佳实践是什么?
以下实际上不是一个很好的例子,但关键是我有一种情况需要做以上尝试做的事情。
(更多情况:现在,我将private C c;
中的class A
更改为
private List<C> someCs;
即:A
是C
的容器,因此在某些情况下需要对这些C
进行排序。对于每个C
的某个客户端,客户端需要知道其父级是什么,即它属于哪个A
。在这种情况下,我需要两个方向的参考。)
答案 0 :(得分:0)
this
在构造函数完成后才是其他对象的有效引用。因此,无法在构造函数中初始化这种循环依赖关系(父级引用子级,子级引用父级)。父子引用也不能是final,因为final必须在构造函数中初始化。
您可以编写一个工厂来初始化所有父母和孩子。然后在所有初始化之后,您可以交叉引用它们。但这需要child.parent
和parent.child
才能被工厂访问。他们是公开的还是有公开的二传手。您还可以执行其他一些特技操作,以允许工厂在父母和子女中设置私有变量,但我不建议这样做。
这是针对您情况的一项建议:创建一个跟踪父母和孩子之间映射的对象。映射具有方法getParent(this)
,在需要父方法时从子方法调用。以及在需要其子级时从父级调用的方法getChildren(this)
和getChildrenSorted(this)
。
该映射可以初始化一次,然后使用private和final锁定,这不会阻止运行时的进一步更改。然后,每个父母和孩子都可以获得对该对象的私有且最终的引用。
有关更多信息: