3

Scala 允许定义update诸如

def update(index: Int, value: String) { ... }

然后像这样称呼它

foo(i) = "Text"

有没有封装它的特征?就像是

trait Update1[+A,+B] {
    def update(i: A, v: B)
}

(当然我可以自己定义这样的特征,但它只适用于我与之混合的实例,而不是与我影响之外构建的其他实例。)

4

1 回答 1

1

您无法定义此类特征的原因是您在不允许使用协变类型参数的地方使用了协变类型参数。以下特征在 Scala 2.10 中编译良好:

trait Update1[-A, -B] {
  def update(i: A, v: B) : Unit
}

trait MyFunction1[-A, +B] {
  def apply(a:A): B
}

trait Mutable[-A, B] extends Update1[A,B] with MyFunction1[A,B]

请注意,为了具有可变特征,您必须修复B参数,因此它既不允许协变也不允许逆变。如果您查看 Scala API 中的可变集合,您会发现实际上它们是这样声明的。

此外,如果您知道该类已经实现了 trait 中定义的方法,那么没有什么可以阻止您在对象中而不是在类中混合 trait 以使编译器满意。例如,您可以拥有以下内容:

class SingleStringCollection(v: String) extends MyFunction1[Int, String] {
  private var someString: String = v
  def apply(a: Int): String =  someString

  def update(i: Int, v: String): Unit = {
    someString = v
  }
  override def toString = someString
}

val test1: Update1[Int, String] = new SingleStringCollection("hi") // this would fail
val test2: Update1[Int, String] = new SingleStringCollection("hi") with Update1[Int, String] // this would work

或者,如果您只想要求您的 val 或参数实现已知方法的列表,您也可以使用结构类型:

type UpdatableStructuralType = {
  def update(i: Int, v: String) : Unit
}

val test3: UpdatableStructuralType = new SingleStringCollection("hi") // this would work
test3(0) = "great" // And of course this would also work

因此,如果您想接受符合某些特征或需要实现某些方法的参数,您有多种选择。

于 2013-11-12T09:15:13.230 回答