Ond*_*žka 10 java generics setter this
我正在努力使API尽可能用户友好.
让我们:
class B extends A {}
class A {
A setX(){ ...; return this; }
}
Run Code Online (Sandbox Code Playgroud)
现在这个
B b = new B().setX();
Run Code Online (Sandbox Code Playgroud)
无效,必须铸造:
B b = (B) new B().setX();
Run Code Online (Sandbox Code Playgroud)
是否有一种方法使用泛型A使编译器知道"this"类型并接受第一种方式 - 没有强制转换并且没有在使用的地方传递类型参数?(不new B<B>().setX(),那很难看.)
我知道为什么Java需要在这种情况下重新输入.请不要回答解释答案setX()A. 我知道.
我在问仿制药能否解决这个问题.
对于那些仍然想告诉我"这就是静态类型如何工作"和"甚至泛型不能帮助解决"的人,请考虑这个有效的Java代码:
Map<String, String> map = new HashMap(){{ put( "foo", new RuntimeException() );
String foo = map.get("foo"); // ClassCastException!!
Run Code Online (Sandbox Code Playgroud)
因此,您可以看到泛型DO允许您在代码中没有出现实际类型转换的情况下获得CCE.
这就是为什么我希望泛型允许摆脱显式类型转换的原因.
此外,IIRC C++允许这样做.
Zho*_*gYu 13
我在这里将部分答案复制到另一个问题,解释了对所谓的"自我类型"的渴望以及Java中的解决方法.
而不是写作
foo.doA();
foo.doB();
Run Code Online (Sandbox Code Playgroud)
很多人宁愿写作
foo.doA().doB();
Run Code Online (Sandbox Code Playgroud)
不幸的是,该语言并不直接支持方法链接,即使它正在成为越来越受欢迎的功能.解决方法是doA()返回foo.它有点脏但可以接受.
但是,如果foo在类型层次结构中,则解决方法会被破坏
class Bar
Bar doA()
class Foo extends Bar
Foo doB();
foo.doA().doB(); // doesn't compile, since doA() returns Bar
Run Code Online (Sandbox Code Playgroud)
所以有些人要求一种特殊的"自我类型"来解决这个问题.假设有一个关键字This来表示"自我类型"
class Bar
This doA()
foo.doA().doB(); // works, doA() returns the type of foo, which is Foo
Run Code Online (Sandbox Code Playgroud)
方法链接似乎是"自我类型"的唯一用例,因此语言可能永远不会引入它(最好直接支持方法链接)
人们发现泛型为这个问题提供了一种解决方法
class Bar<This>
This doA()
class Foo extends Bar<Foo>
Foo has a method "Foo doA()", inherited from Bar<Foo>
Run Code Online (Sandbox Code Playgroud)
这是该模式最常用的用例A extends B<A>.这是一个孤立的解决方法/技巧.它在A和B之间的关系中没有添加语义.
这也是一个流行的做法,以约束This像
class Bar<This extends Bar<This>>
Run Code Online (Sandbox Code Playgroud)
这是丑陋和无用的,我强烈建议反对它.只需使用"This"作为约定来表示它的用途.
小智 6
在 A 类中试试这个:
public <T extends A> T setX() {
return (T) this;
}
Run Code Online (Sandbox Code Playgroud)
你可以像这样使用它
B b = new B().setX();
Run Code Online (Sandbox Code Playgroud)