I have a situation where I always need to run a certain bit of code that depends on the object itself
public abstract class A{
public A(X x){
//init A stuff
x.getAList("stuff").add(this);
x.getAList("otherstuff").add(this);
}
}
public class B extends A{
public B(X x){
super(x);
//init B stuff
}
}
public class C extends A{
public C(X x){
super(x);
//init C stuff
x.getAList("otherstuff").remove(this);
x.getAList("morestuff").add(this);
}
}
public class SomeClass{
private X someX;
public A somefunc(boolean b){
if(b){
return new B(someX);
}else{
return new C(someX);
}
}
}
The problem is the following. In this example I use this
in the constructor. If another thread tries to access the object through someX.getAList, it could cause that thread to get access to the object before the constructor has ended.
You could make it so that the object gets added to the AList by somefunc
public class SomeClass{
private X someX;
public A somefunc(boolean b){
A a;
if(b){
a = new B(someX);
someX.getAList("stuff").add(a);
someX.getAList("otherstuff").add(a);
}else{
a = new C(someX);
someX.getAList("stuff").add(a);
someX.getAList("morestuff").add(a);
}
return a;
}
}
The problem is that B's and C's could also be instantiated elsewhere and that everytime a B or C is created they would need to be added in that specified way. I don't want adding the object to the AList to be the responsibility of the user, but of the class. I also don't want the user to have to call an init function that does this for them. On the other hand, I don't want any concurrency issues.
Is there a way or a pattern that makes it possible to implement this?
Golang has something like defer that lets you run a piece of code after the function/method/constructor is done.
Yes, as mentioned we can call all the members of a class (methods, variables, and constructors) from instance methods or, constructors.
For the global object, the constructors are called before entering into the main function.
12.1 Constructors and destructors A constructor is a special initialization function that is automatically called whenever a class is declared.
When a class object is created using constructors, the execution order of constructors is: Constructors of Virtual base classes are executed, in the order that they appear in the base list. Constructors of nonvirtual base classes are executed, in the declaration order.
Make a Factory-Method for the super and subclass instead and make the constructors private, forcing everyone who wants an instance to use the factory method. A factory method is a method that returns a completely constructed instance. Once the instance is completely constructed (after the constructor was called in the factory method) add the instance to the list, that way no thread can get hold of a incomplete/non-finalized instance.
The point of the Factory-Method is to strictly isolate all the initialisation code from any non-initialisation code, to avoid access to and exposure of uninitialised fields. Also it can serve as a selector for users, automatically returning a suitable (sub-)type, without having to be specified.(Interesting design-patterns)
abstract class A{
protected A(){
//constructor code goes here
}
public void afterFinalisation(final X x) {
x.getAList("stuff").add(this);
x.getAList("otherstuff").add(this);
}
}
class B extends A{
protected B(){
super();
//constructor code goes here
}
public static B create(final X x) {
final B returnValue = new B();
returnValue.afterFinalisation(x);
return returnValue;
}
}
class C extends A{
protected C(){
super();
//constructor code goes here
}
@Override
public void afterFinalisation(final X x) {
super.afterFinalisation(x);
x.getAList("otherstuff").remove(this);
x.getAList("morestuff").add(this);
}
public static C create(final X x) {
final C returnValue = new C();
returnValue.afterFinalisation(x);
return returnValue;
}
}
class SomeClass{
private final X someX = new X();
public A somefunc(final boolean b){
if(b){
return B.create(this.someX);
}else{
return C.create(this.someX);
}
}
}
The credit for the constructor code goes to coolcats iteration of my answer, I was trying to avoid putting code into the protected constructors and worked with a init() method instead, which required a big unelegant-workaround for final fields.
By taking a few design decisions from HopfullyHelpful I end up with liking the following design best:
public abstract class A{
protected A(X x){
//constructor with all inits
}
protected A publish(X x) {
x.getAList("stuff").add(this);
x.getAList("otherstuff").add(this);
return this;
}
}
class B extends A{
protected B(X x){
super(x);
//constructor with all inits
}
protected B publish(X x) {
super.publish(x);
return this;
}
public static B create(X x) {
return new B(x).publish(x);
}
}
class C extends A{
protected C(X x){
super(x);
//constructor with all inits
}
protected void publish(X x) {
super.publish(x);
x.getAList("otherstuff").remove(this);
x.getAList("morestuff").add(this);
return this;
}
public static C create(X x) {
return new C(x).publish(x);
}
}
class SomeClass{
private X someX;
public A somefunc(boolean b){
if(b){
return B.create(this.someX);
}else{
return C.create(this.someX);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With