Java泛型:使用这种类型作为返回类型? [英] Java generics: Use this type as return type?

查看:597
本文介绍了Java泛型:使用这种类型作为返回类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



让我们来:

  class B extends A {} 

class A {
setX(){...;返回这个; }
}

现在这个

  B b = new B()。setX(); 

无效,必须进行转换:

  B b =(B)new B()。setX(); 

A 让编译器意识到this类型并接受第一种方式 - 无需在使用的位置进行投射和传递类型参数? (即不是新的B ().setX(),这很丑。)我知道为什么Java在这种情况下需要重新输入。请不要回答解释 setX()返回A. 我知道。
我在问if泛型可以解决这个问题。



对于那些仍然想告诉我这就是静态类型的工作方式和甚至没有泛型可以帮助解决这个问题有效的Java代码:

  Map< String,String> map = new HashMap(){{put(foo,new RuntimeException()); 
String foo = map.get(foo); // ClassCastException !!

所以你可以看到,泛型DO可以让你获得一个CCE而不会在代码中出现实际的类型转换。

这就是为什么我希望泛型允许摆脱显式类型转换的原因。



另外,IIRC C++允许

解决方案

我复制了部分回答另一个问题,解释对所谓自我类型的渴望以及Java中的解决方法。

方法链接



而不是写作

  foo.doA(); 
foo.doB();

很多人都希望写作

  foo.doA()DOB(); 

不幸的是,这种语言并不直接支持方法链接,尽管它正在变得越来越受欢迎。解决方法是为 doA()返回 foo 。这有点脏但可以接受。然而,如果 foo 处于类型层次结构中,则解决方法将被打破。

  class Bar 
Bar doA()

class Foo extends Bar
Foo doB();

foo.doA()。doB(); //不会编译,因为doA()返回Bar

所以有些人要求一个特殊的自我型来解决这个问题。假设有一个关键字这个来表示自我类型

  class Bar 
这个doA()

foo.doA()。doB(); //工作,doA()返回foo的类型,它是Foo

看起来,方法链接是自我类型的唯一用例,因此语言可能永远不会引入它(直接支持方法链接更好)。

人们发现泛型提供了解决此问题的方法

  class Bar< This> 
这个doA()

class Foo扩展了Bar< Foo>

Foo有一个方法Foo doA(),继承自Bar< Foo>

这是 A extends B< A> 模式。这是一个孤立的解决方法/技巧。它在A和B之间的关系中不增加任何语义。



约束这个 / p>

  class Bar<这扩展了Bar< This>> 

这是丑陋而无用的,我强烈建议不要。只需使用This作为惯例即可表明其用途。


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<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<String, String> 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.

Also, IIRC C++ allows that.

解决方案

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>
    This doA()

class Foo extends Bar<Foo>

Foo has a method "Foo doA()", inherited from Bar<Foo>

This is the most popular use case for the A extends B<A> 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<This extends Bar<This>>

It is ugly and useless, I strongly recommend against it. Simply use "This" as a convention to indicate what it is for.

这篇关于Java泛型:使用这种类型作为返回类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆