如果我定义一个返回存在类型的方法:
myX
如果我调用X[_]
,我会得到一个类型val y: Any = 123
myX.hello(y) // compilation error!
的值,但我无法传递任何内容:
Nothing
我只能传递val y: Nothing = ???
myX.hello(y) // compilable, but useless
:
require
因此,返回存在类型的方法没有意义吗?
答案 0 :(得分:3)
scala> trait X[T] {
| def hello(x: T):Unit = println(x)
| }
defined trait X
您对函数的定义:
scala> def myX: X[_] = new X[Any] {}
myX: X[_]
scala> val xnothing = myX
xnothing: X[_] = $anon$1@5c44c582
scala> xnothing.hello(1)
<console>:14: error: type mismatch;
found : Int(1)
required: _$1
xnothing.hello(1)
^
“固定”相同功能的定义 - 正确捕获类型arg:
scala> def myY[T]: X[T] = new X[T] {}
myY: [T]=> X[T]
如果未通过通用arg,则推断Nothing
。
scala> val ynothing = myY
ynothing: X[Nothing] = $anon$1@53f0a4cb
您可以显式传递通用arg。
scala> val yint = myY[Int]
yint: X[Int] = $anon$1@555cf22
显然Int
不是Nothing
。
scala> ynothing.hello(1)
<console>:14: error: type mismatch;
found : Int(1)
required: Nothing
ynothing.hello(1)
^
这显然有效,因为我们明确地传递了Int
:
scala> yint.hello(1)
1
现在这是一个有趣的部分。它的工作原理是因为Scala可以发现泛型arg是Int
(来自用法)。将其与上面的ynothing
定义及其无法编译的调用ynothing.hello(1)
进行对比。
scala> myY.hello(1)
1
答案 1 :(得分:3)
返回此存在类型没有多大意义,但在其他情况下它们可能很有用。作为一个简单的例子
// method which returns an existential type
// note that you can't return Array[Any] here,
// because arrays aren't covariant in Scala (which is a good thing)
def array: Array[_] = if (some condition) Array[Int](...) else Array[Double](...)
// all of following works
array(0)
array.length
// etc.
当然,如果你可以编写一个方法的精确泛型类型,你肯定会喜欢它。