Reputation: 1703
So I have a couple of inherited classes defined like so.
class Base {
public Base chainedMethodA() {
// some stuff
return this;
}
}
class Derived extends Base {
public Derived chainedMethodB() {
// some stuff
return this;
}
}
Now, the following code works:
Derived obj = new Derived();
obj.chainedMethodB().chainedMethodA();
But this does not (notice the switched order of function calls):
Derived obj = new Derived();
obj.chainedMethodA().chainedMethodB();
The compiler gives an error on the chainedMethodB()
function call. I can understand that this is because when you run chainedMethodA()
, it returns an object of type Base
, which does not have chainedMethodB
defined.
I can think of a few solutions to this problem:
Derived
's methods first, and then call Base
's methods). This looks like a very brittle solution.chainedMethodA
in Derived
so it returns an instance of Derived
instead of Base
. This looks like a waste of inheritance.Is there any elegant way around this problem? Maybe some construct that magically changes chainedMethodA
to return a Derived
instance when called by an object of type Derived
, without being explicitly overridden in Derived
.
Upvotes: 4
Views: 773
Reputation: 2790
Override
chainedMethodA
inDerived
so it returns an instance ofDerived
instead of Base. This looks like a waste of inheritance.
You're wrong. You aren't wasting inheritance.
Technique of overriding is to do just that namely specialize a method. Override can be done when the returned type is the same or a subtype of the return type declared in the original overridden method in the superclass. So in this case you are violating nothing.
Read here for more about overriding.
Here example 1: (calling the superclass method)
public class Derived extends Base {
@Override
public Derived chainedMethodA(){
super.chainedMethodA();
//some stuff
return this;
}
public Derived chainedMethodB() {
// some stuff
return this;
}
}
Here example 2: (changing it completele)
public class Derived extends Base {
@Override
public Derived chainedMethodA(){
//some stuff
return this;
}
public Derived chainedMethodB() {
// some stuff
return this;
}
}
Upvotes: 2
Reputation: 24354
In this situation inheritance is probably the simplest solution.
However, your last sentence pretty much explains generics:
Maybe some construct that magically changes chainedMethodA to return a Derived instance when called by an object of type Derived, without being explicitly overridden in Derived.
So something like this may be useful in other similar use cases:
static class Base {
public <T extends Base> T chainedMethodA(Class<T> clazz) throws Exception {
// some stuff
return clazz.cast(this);
}
}
static class Derived extends Base {
public Derived chainedMethodB() {
// some stuff
return this;
}
}
public static void main(String args[]) throws Exception {
Derived obj = new Derived();
obj.chainedMethodA(Derived.class).chainedMethodB();
}
Upvotes: 0