Reputation: 3742
I have children classes that use composition with classes that are also children. Instead of having a similar getter in each child class how can I move the getter of the composition class to the parent.
public class child1 extends Parent {
private CoolObjectTypeAAA coolObject;
//coolObject getter
}
public class child2 extends Parent {
private CoolObjectTypeBBB coolObject;
//coolObject getter
}
public class CoolObjectTypeAAA extends CoolObject {
}
public class CoolObjectTypeBBB extends CoolObject {
}
public abstract class Parent {
//would like to have a single CoolObject getter here in parent that returns the appropriate cool object of each child.
}
Is this possible or do I need to just have similar getter in each child class?
Upvotes: 0
Views: 550
Reputation: 3523
I would suggest taking a look at the abstract factory pattern as this seems to be what you are trying to accomplish. Properly implemented it involves multiple abstract classes and many subclasses but it is not as daunting as it seems.
What you are trying to do basically looks like a compact version of this but it is generally not a great approach as it leads to difficult to follow OO spaghetti code that jumps back and forth between the parent and subclass.
Remember, you've already defined Parent as abstract for a reason.
I suspect your goal is to maximise code reuse, normally when I see this kind of code it is because there is some common "CoolObject" init code that you don't want to duplicate in the child classes.
In that case, it is typically better to write a common "CoolObject" private or protected initializer in the parent but still construct the specific type of CoolObject in the child classes and then initialize it via the parent class method before returning it from the child.
In this case, since it is a getter, there may not be anything other than returning the private object. If that is the case then the best thing is to define a generic getter as abstract in Parent and then redefine in each child. The primary issue with this is that wherever you use this code you will need to continually typecast to the specific type of CoolObject you are expecting.
Because of this, it is likely that down the line, even if you provide either an abstract CoolObject getter or a concrete CoolObject getter in Parent, you will still end up wanting to have concrete implementations of getters for the specific CoolObject types.
The thing to keep in mind when designing something like this is how is it going to be used.
If the goal is to provide an abstraction over the various types of CoolObject then you are basically using a strategy pattern. In this case, being able to cast variables to the sub-type of CoolObject is not needed. In that case a non-specific type getter (abstract or concrete) is feasible.
Having the two specific child classes of Parent, however, it doesn't feel like this is what you are going for. Again I would suggest taking a look at the abstract factory pattern as this seems more like what you trying to do.
Upvotes: 1
Reputation: 2336
How about this:
abstract class Parent<T extends CoolObject> {
protected T mCoolObject;
public Parent(T coolObject) {
mCoolObject = coolObject;
}
public T getCoolObject() {
return mCoolObject;
}
}
class Child1 extends Parent<CoolObjectTypeAAA> {
public Child1(CoolObjectTypeAAA coolObject) {
super(coolObject);
}
public void demoType() {
// This type checks as the return type of getCoolObject() has been refined to CoolObjectTypeAAA
CoolObjectTypeAAA co = this.getCoolObject();
}
}
class Child2 extends Parent<CoolObjectTypeBBB> {
public Child2(CoolObjectTypeBBB coolObject) {
super(coolObject);
}
public void demoType() {
// This type checks as the return type of getCoolObject() has been refined to CoolObjectTypeBBB
CoolObjectTypeBBB co = this.getCoolObject();
}
}
abstract class CoolObject { }
class CoolObjectTypeAAA extends CoolObject { }
class CoolObjectTypeBBB extends CoolObject { }
Essentially you make the subclass specify whatever specific subtype of CoolObject
it uses so that it can refine the return type of the getter, yet you get to implement the getter in the super class.
Upvotes: 1