以下我有:
trait Elem {
def compare: Int
}
case class DiffElem(weight: Int, len: Int) extends Elem {
def compare = weight - len;
}
现在基于compare
函数可以有许多Elem的子类。
现在我有一个函数,它从文件读取输入并生成DiffElem
的列表:
def getInput[T <: Elem](): List[T] = {
var ans: List[T] = List.empty[T]
for (line <- Source.fromFile("src/week1/jobs.txt").getLines()) {
val diff = line.split(" ")
ans = ans match{
case i:List[DiffElem] => new DiffElem(Integer.parseInt(diff(0)), Integer.parseInt(diff(1))) :: ans;
case _ => ???
}
}
ans
}
但编译器不允许该操作,显然::
遵循反向方差类型,我试图做不变性。如果我将函数签名转换为T >: Elem
,那么它可以工作,但目的没有解决。
有更好的方法吗?
答案 0 :(得分:3)
如果你在getInput中构建DiffElem,那么你想获得任意T&lt;:Elem列表的方式(以及为什么)?要做这样的事情,你应该能够从DiffElem转换为任何另一个T&lt;:Elem,并且可以使用隐式捕获可转换性:
def getInput[T <: Elem](implicit conv: DiffElem => T): List[T] = ...
,但你真的想要吗?如果您对DiffElem的列表感到满意,可以用这种方式重写功能:
def getInput(): List[DiffElem] =
Source.fromFile("src/week1/jobs.txt").getLines().map { line =>
val diff = line.split(" ")
DiffElem(
Integer.parseInt(diff(0)),
Integer.parseInt(diff(1))
)
} toList
map是高阶函数,它捕获序列中每个元素的变换,并将其funarg应用于此元素。
<强>更新强>: 为了制作模块化类型驱动列表,我建议使用:
def getInput[E <: Elem](implicit mkE: (Int, Int) => E): List[E] = {
Source.fromFile("src/week1/jobs.txt").getLines().map { line =>
val diff = line.split(" ")
mkE(diff(0).toInt, diff(1).toInt)
} toList
}
现在,对于您想要获得的任何E&lt;:Elem,列表,您应该提供类型(Int,Int)=&gt;的隐式值。 E进入范围,如:
implicit val diffElemBuilder = {
(a, b) => DiffElem(a, b)
}
在任何可见的隐式范围内,您都可以使用这样的getInput:
val xs = getInput[DiffElem]
答案 1 :(得分:-1)
您可以重新构建代码并使用排名较高的多态函数而不是模式匹配。