0

下面我有:

trait Elem {
  def compare: Int
}

case class DiffElem(weight: Int, len: Int) extends Elem {
  def compare = weight - len;
}

现在可以有很多 Elem 的子类,基于compare函数。现在我有一个函数,它从文件中读取输入并生成一个列表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然后它可以工作,但目的没有解决。

有更好的方法吗??

4

2 回答 2

3

如果您在 getInput 中构建 DiffElem,那么您希望如何(以及为什么)获取任意 T <: Elem 的列表?要执行此类操作,您应该能够从 DiffElem 转换为任何另一个 T <: 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 <: Elem,列表,您应该在范围内提供类型 (Int, Int) => E 的隐式值,例如:

  implicit val diffElemBuilder = {
    (a, b) => DiffElem(a, b)
  }

在任何范围内,如果隐式可见,您可以像这样使用 getInput:

val xs = getInput[DiffElem]
于 2012-12-16T13:37:22.463 回答
-1

您可以重构代码并使用更高级别的多态函数而不是模式匹配。

于 2012-12-16T13:44:58.347 回答