我有以下特点:
trait SomeTrait {
def doSomething[V](msg: Message[V]): Message[V]
}
Message [V]是一个案例类如下:
case class Message[V](elems: Map[String, V])
我现在有一个调用doSomething方法的方法如下:
val someWork = new SomeTrait {
override def doSomething[Int](msg: Message[Int]): Message[Int] = {
msg.copy(elems = msg.elems.map {
case (k, v) => (k, v + 1) // It fails here!!!
})
}
}
我得到一个奇怪的编译器错误说:
Error:(16, 32) type mismatch;
found : Int(1)
required: String
Error occurred in an application involving default arguments.
case (k, v) => (k, v + 1)
我在某个地方傻了吗?
答案 0 :(得分:3)
注意:您的Int
不是scala Int
。您将Scala [Int]
隐藏在泛型类型名称后面 - 您所编写的内容看起来像是C ++中的模板特化,但是泛型在Scala中不能以这种方式工作。在代码中将[XXX]
替换为V
时,您将收到相同的错误。
覆盖方法时无法更改类型签名。由于特征承诺您接受任何类型case class Message[V](elems: Map[String, V])
trait SomeTrait {
def doSomething[V: MapValue](msg: Message[V])
}
trait MapValue[V] {
def map(v: V): V
}
implicit object MapValueInt extends MapValue[Int] {
def map(v: Int) = v + 1
}
val someWork = new SomeTrait {
override def doSomething[X: MapValue](msg: Message[X]) = {
val evidence = implicitly[MapValue[X]]
msg.elems.map {
case (k, v) => k -> evidence.map(v)
}
}
}
而没有任何约束,因此实现需要满足此承诺。
C ++ - 就像使用type classes一样可以实现专业化 - 您通过承诺将根据需要提供专门的实现来扩展您的合同:
{{1}}
答案 1 :(得分:1)
@Suma所说的......在这种情况下,您也可以参数化特征而不是方法。它不那么通用,但有点简单:
trait SomeTrait[V] {
def doSomething(msg: Message[V]): Message[V]
}
val someWork = new SomeTrait[Int] {
def doSomething(msg: Message[Int]) = msg.copy(msg.elems.mapValues(_ + 1)
}