[英]In Java, can a class reference the instance of another class which contains it?
class A {
private B b = new B();
}
class B {
private A a;
public void setA(A a){
this.a = a
}
}
setA
is called after an instance of A has been initiated. 在启动A的实例后调用
setA
。 I want to do this becase A
has a method that B
wants to call inside it. 我想这样做,因为
A
有一个B
想要在其中调用的方法。
Sure, the language allows to do that. 当然,这种语言允许这样做。
But by doing this, you create what is called a circular dependency. 但是通过这样做,您可以创建所谓的循环依赖关系。 A needs B, and B needs A. That is considered bad practice in many cases.
A需要B,而B需要A。在许多情况下,这被视为不良做法。
So, the real answer would be to step back and look at the problem you intend to solve. 因此,真正的答案是退后一步,看看您打算解决的问题。 And to then design a solution that does not create a circular dependency!
然后设计一个不会产生循环依赖的解决方案! Sometimes bidirectional connectivity is necessary, but in general, it can quickly become a source for potential problems later in. So do not buy into such a solution unless you have carefully evaluated your options and you didn't find a better way.
有时双向连接是必要的,但通常,它很快就会成为以后潜在问题的根源。因此,除非您仔细评估了自己的选择并且没有找到更好的方法,否则不要购买这种解决方案。
It might be helpful for example that method that B needs in an interface. 例如,接口B需要的方法可能会有所帮助。 Then your B object only needs an instance of that interface (which could be an A under the covers).
然后,您的B对象只需要该接口的一个实例(可以是一个A)。
Here A composes B. 这里A组成B。
class A {
private B b = new B();
}
And here B composes A : B组成A:
class B {
private A a;
public void setA(A a){
this.a = a
}
}
No design judgement, supposing that you are in a case where the bidirectional dependency is needed, you should avoid initializer or constructor to create instances of this class since you need an instance from A to create B and reversely. 无需设计判断,假设您需要双向依赖,则应避免使用初始化程序或构造函数来创建此类的实例,因为您需要A的实例来创建B,反之亦然。 Making this in an asymmetric way as in your sample code hides in a some way the relationship between these two classes.
如您的示例代码中那样,以非对称方式进行此操作以某种方式隐藏了这两个类之间的关系。
So you could use a setter or a factory approach to make it clearer. 因此,您可以使用设置器或工厂方法来使其更清晰。
Setter approach : 设置方法:
class A {
private B b;
public void setB(B b){
this.b = b;
}
}
class B {
private A a;
public void setA(A a){
this.a = a
}
}
A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
Or with a factory approach where you can rely on A or B class to expose the factory method according to the client need POV : 或者使用工厂方法,您可以根据客户的需求POV依赖于A或B类公开工厂方法:
class A{
// ...
public static A ofWithB(){
A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
return a;
}
}
A a = A.ofWithB();
B b = a.getB();
Any time code (in B
in your example) has a reference to an instance of a different class ( A
in your example), the rules governing its access to that instance's members (methods and fields) are the same: 任何时候代码(在您的示例中为
B
)引用不同类的实例(在您的示例中为A
)时,用于控制对该实例成员(方法和字段)的访问的规则是相同的:
private
, B
cannot access it private
成员,则B
无法访问它 protected
, B
can access it only if B
and A
are in the same class, or B
is a subclass of A
protected
,则只有当B
和A
属于同一类,或者B
是A
的子类时, B
才能访问它 B
can only access it if B
and A
are in the same package B
仅在B
和A
位于同一包中时才能访问它 public
, B
can access it public
,则B
可以访问它 (In an interface, no access modifier = public
and you can't have other access modifiers.) (在界面中,没有访问修饰符=
public
并且您不能有其他访问修饰符。)
It doesn't matter whether the instance is held on a field of an instance of B
. 实例是否保留在
B
实例的字段上并不重要。 The only thing that matters is what class the code trying to perform the access is in. 唯一重要的是试图执行访问的代码位于哪个类中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.