I have a parent class, which defines a collection of chainer methods (methods that return "this"). I want to define multiple child classes that contain their own chainer methods but that also "override" the parent methods so that an instance of the child class is returned instead of the parent class.
I don't want to have to repeat the same methods in each child class, which is why I have a parent class that contains the methods that all the child classes share. Thanks.
class Chain {
public Chain foo(String s){
...
return this;
}
}
class ChainChild extends Chain {
//I don't want to add a "foo" method to each child class
/*
public ChildChain foo(String s){
...
return this;
}
*/
public ChainChild bar(boolean b){
...
return this;
}
}
ChainChild child = new ChainChild();
child.foo().bar(); //compile error: foo() returns a "Chain" object which does not define the bar() method.
Method Chaining is the practice of calling different methods in a single line instead of calling other methods with the same object reference separately. Under this procedure, we have to write the object reference once and then call the methods by separating them with a (dot.).
Method chaining, also known as named parameter idiom, is a common syntax for invoking multiple method calls in object-oriented programming languages. Each method returns an object, allowing the calls to be chained together in a single statement without requiring variables to store the intermediate results.
The drawback to self-referential method chaining is that you communicate that multiple method calls are required to do something, and that each call builds off the last. If this is not true, then method chaining could be communicating the wrong thing to other programmers.
Inheritance in OOP = When a class derives from another class. The child class will inherit all the public and protected properties and methods from the parent class. In addition, it can have its own properties and methods. An inherited class is defined by using the extends keyword.
A method in the parent class that returns this
will still return a reference to the object of the child class. You will only be able to treat it as an object of the parent class (unless you cast it) but it will actually be of its original type.
You could consider using generics like this:
// This seems a bit too contrived for my liking. Perhaps someone else will have a better idea.
public class Parent<T extends Parent<T>> {
T foo () {
return (T) this;
}
}
public class Child extends Parent<Child> {
public void bar () {
Child c = foo();
}
}
I've written this sample using generics based on your needs.
class Parent {
public <T extends Parent> T foo() {
return (T)this;
}
}
class Child extends Parent {
}
class AnotherChild extends Parent {
}
public class Test {
public static void main(String[] args) {
Parent p = new Child();
System.out.println(p);
Child c = p.foo();
System.out.println(c);
//throws ClassCastException here since Child is not AnotherChild
AnotherChild ac = p.foo();
System.out.println(ac);
}
}
Here's an improvement on OldCurmudgeon's method:
public class Parent<This extends Parent<This>> {
@SuppressWarnings("unchecked")
private final This THIS = (This)this;
public This foo() {
//...
return THIS;
}
public This bar() {
//...
return THIS;
}
}
public class Child extends Parent<Child> {
// you can override super with covariant return type
@Override
public Child bar() {
super.bar();
return this;
}
}
Child child =
new Child()
.foo()
.bar();
The improvement is making an unchecked cast only once and save it to a constant THIS, which you can reuse as the return value for method chaining.
This removes unchecked casts in every method and makes the code clearer.
You can override Parent's methods by returning Child instead of This (covariant return type).
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