Scala中的实例类型参数化

时间:2013-11-26 09:11:43

标签: scala generics

来自Java,我正在尝试开发简单的SQL生成器,这里是这段代码的基础:

abstract class Model(val id: Long)

trait Sqlizer[A] {
  def insert(model: A, ret: Boolean = false): String
}

trait Transactor {
  def insert[A <: Model](row: (A, Sqlizer[A])): Transactor

  def commit(): Boolean
}

object Transactor {
  def apply() = new DefaultTransactor
}

class DefaultTransactor extends Transactor {
  private var queries: List[(_ <: Model, Sqlizer[_ <: Model])] = List()

  def insert[A <: Model](row: (A, Sqlizer[A])): Transactor = {
    queries = queries :+ row
    this
  }

  def commit(): Boolean = {
    val body = queries map { kv =>
      kv._2 insert kv._1
    }

    true
  }
}

如果我没错,_ <: Model就像Java的? extends Model,一切都应该没问题。但是我在填写这个文件时遇到错误:

Transactor.scala:27: error: type mismatch;
 found   : kv._1.type (with underlying type _$1)
 required: _$2
      kv._2 insert kv._1 

我应该如何参数化我的查询var以使其正确?或者我应该更改整个键入策略以移动Scala方式。感谢。

1 个答案:

答案 0 :(得分:2)

这里的问题是,当你写queries: List[(_ <: Model, Sqlizer[_ <: Model])]时,它表示该对中的第一个元素必须是扩展Model的某种类型,而第二个元素必须是Sqlizer类型的参数化某些类型也扩展了Model,但并没有说这两种类型必须相同。由于类型可能不同,Sqlizer.insert将无效,因为类型可能不兼容 - 如果Sqlizer[A].insert(param: B)A都延伸{{1},则无法调用B但是不是同一种类型。下面是一个修改版本,我将该对更改为案例类。由于case类是用单一类型参数化的,因此它的Model方法知道它所拥有的模型和sqlizer是兼容的。

insert