Reputation: 641
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. I want to do this becase A
has a method that B
wants to call inside it.
Upvotes: 1
Views: 1288
Reputation: 131456
Here A composes B.
class A {
private B b = new B();
}
And here B composes 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. 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 :
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();
Upvotes: 3
Reputation: 140525
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.
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. Then your B object only needs an instance of that interface (which could be an A under the covers).
Upvotes: 3
Reputation: 1074979
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:
private
, B
cannot access itprotected
, B
can access it only if B
and A
are in the same class, or B
is a subclass of A
B
can only access it if B
and A
are in the same packagepublic
, B
can access it(In an interface, no access modifier = public
and you can't have other access modifiers.)
It doesn't matter whether the instance is held on a field of an instance of B
. The only thing that matters is what class the code trying to perform the access is in.
See Controlling Access to Members of a Class
Upvotes: 1