I'm trying to make an API as user friendly as possible.
Let's have:
class B extends A {}
class A {
A setX(){ ...; return this; }
}
Now this
B b = new B().setX();
is invalid, has to be casted:
B b = (B) new B().setX();
Is there a way using generics in A to make compiler aware of "this" type and accept the first way - without casting and without passing type parameter at the place where used? (I.e. not new B().setX(), that's ugly.)
I KNOW why Java needs retyping in this case. Please no answers explaing that setX() returns A. I know that.
I am asking if generics can solve this.
And for those still wanting to tell me that "this is how static typing works" and "not even generics can help with that", consider this valid Java code:
Map map = new HashMap(){{ put( "foo", new RuntimeException() );
String foo = map.get("foo"); // ClassCastException!!
So you can see that generics DO allow you get a CCE without actual type cast appearing in the code.
That's the reason why I expect generics to allow getting rid of the explicit type cast.
解决方案
I copy part of the answer to another question here, explaining the desire for the so called "self type" and the workaround in Java.
Method Chaining
Instead of writing
foo.doA();
foo.doB();
a lot of people would rather want to write
foo.doA().doB();
Unfortunately the language doesn't directly support method chaining even though it is becoming an increasingly desired feature. The workaround is for doA() to return foo. It is a little dirty but acceptable.
However if foo is in a type hierarchy the workaround is broken
class Bar
Bar doA()
class Foo extends Bar
Foo doB();
foo.doA().doB(); // doesn't compile, since doA() returns Bar
So some people call for a special "self type" to solve this problem. Let's say there's a keyword This to represent "self type"
class Bar
This doA()
foo.doA().doB(); // works, doA() returns the type of foo, which is Foo
It appears that method chaining is the only use case for "self type", so the language probably will never introduce it (it's better to just support method chaining directly)
People found out that generics provides a workaround for this problem
class Bar
This doA()
class Foo extends Bar
Foo has a method "Foo doA()", inherited from Bar
This is the most popular use case for the A extends B pattern. It is an isolated workaround/trick. It adds no semantics in relationship between A and B.
It is also a popular practice to constraint This like
class Bar>
It is ugly and useless, I strongly recommend against it. Simply use "This" as a convention to indicate what it is for.