方法返回类型协方差

Nut*_*tel 2 scala

如何定义该方法返回List [+ AnyRef]?我试过了:

def a[T <: AnyRef](): List[T] = List[AnyRef]() 
Run Code Online (Sandbox Code Playgroud)

但由于某种原因,它无法编译.

编辑:根据王我应该使用

def a[T <: AnyRef](): List[T] = List[T]()
Run Code Online (Sandbox Code Playgroud)

但是,有没有办法能够返回AnyRef的任何子类型,例如

def a[T <: AnyRef](): List[T] = if (value) List[T]() else List[Option[String]]()
Run Code Online (Sandbox Code Playgroud)

这里Option [String]是Anyref的后代,但编译器不接受它

所以主要问题是我是否可以使用协变返回类型声明方法,如List [+ AnyRef]

Y.H*_*ong 5

让我们做几个观察并试验一些让编译器决定你的返回类型的方法:

1)请注意,该语句if (value) List[T]() else List[Option[String]]()返回2种不同的特定类型,但该if语句必须从其then和else子句返回相同的类型.因此,当此语句返回一个值时,编译器将需要推断出2个子句的最常规类型,以引入一致的约束.

2)请注意,类型变量T是依赖于你,当你调用传递的确切类型a(),例如a[scala.io.Source]().在方法声明中,您给出了T一个上限T <: AnyRef,这意味着编译器必须找到最常规的类型,它是AnyRef和Option [String]子类型的任何类型的并集.

3)注意编译器通过删除返回类型声明推断出的返回类型.即def a[T <: AnyRef]() = if (true) List[T]() else List[Option[T]]().编译器给出a()了返回类型List[AnyRef].这种意义是有道理的,因为这是T任何子类型AnyRefOption[of that anything T].之间最通用类型的唯一可能性.

4)现在试试def a[T <: AnyRef]() = if (true) List[T]() else List[Option[String]]().现在推断出返回类型List[java.lang.Object].原因是StringScala 2.8中的类实际上是java.lang.String,所以根据我的最佳猜测,现在最常见的类型必须逃离scala.*层次结构并最终导致java.lang.Object未知原因.

5)因为AnyRef实际上只是别名java.lang.Object,你可以def a[T <: AnyRef](): List[AnyRef] = if (true) List[T]() else List[Option[String]]()强制执行返回类型List[AnyRef].

如果您只想返回AnyRef的任何子类型,您基本上必须这样做:

def a(): List[AnyRef] = ...
Run Code Online (Sandbox Code Playgroud)

它基本上返回超类,你必须List[AnyRef]使用返回的方式.asInstanceOf[T].或者:

def a[T <: AnyRef](): List[T] = List[T]()
Run Code Online (Sandbox Code Playgroud)

将为您提供特定的类型T,但是您不能if在示例中返回两种不同的类型,其中一个可能更具体而另一个,并期望它始终返回您提供的更具体的类型调用方法.因为编译器无法if通过类型检查来保证语句中的类型始终是List [T].我是否更清楚了?