我有一个功能,我无法进行类型推断。完整的示例代码如下,但有问题的功能是:
def mapObjects[T, S <: HasGetter[T]](lst: GenSeq[S]): GenSeq[T] = {
lst map {v => v.getT}
}
问题是调用mapObjects需要明确命名类型T和S.有没有办法编写这个函数的类型签名,以便推理正常工作?
工作示例代码:
import scala.collection.GenSeq
trait HasGetter[T] {
def getT: T
}
class HasStringGetter(str: String) extends HasGetter[String] {
override def getT = str
}
object TypeInferenceTest {
def mapObjects[T, S <: HasGetter[T]](lst: GenSeq[S]): GenSeq[T] = {
lst map {v => v.getT}
}
def tst {
val objs = List(new HasStringGetter("abc"), new HasStringGetter("def"), new HasStringGetter("hij"))
// Doesn't typecheck
// val strs = mapObjects(objs)
val strs = mapObjects[String, HasStringGetter](objs)
}
}
答案 0 :(得分:4)
如何:
def mapObjects[T](lst: GenSeq[HasGetter[T]]): GenSeq[T] = {
lst map {v => v.getT}
}
scala> mapObjects(objs)
res18: scala.collection.GenSeq[String] = List(abc, def, hij)
在您的案例中使用S <: HasGetter[T]
没有任何明显优势,因为您只是在lst
上执行地图并获取T
类型的元素。并且函数的返回类型与类型S
无关。因此,无需获得精确类型S
如果明确需要函数或函数体的返回类型来维护类型S <: HasGetter[T]
,则需要您的代码。但在这种情况下,没有必要保持这种类型。
此外GenSeq[+A]
是协变型。因此,默认情况下,它可以接受参数中属于GenSeq[ <: HasGetter[_]]
的类型。 GenSeq
不是共同变体,它本来是一个不同的问题。