Hug*_*ira 1 generics scala variance
考虑下面的例子,它应该打印8.为什么A.Value + B.Value认为B.Value应该是一个字符串?我如何解决它?
object Catano extends App {
val const3 = new Constant(3)
val const5 = new Constant(5)
val block = new Arithmetic(const3.Result, const5.Result)
println(block.Sum.Value)
}
class Block
class Arithmetic[T: Numeric](val A: Connector[T], val B: Connector[T]) extends Block {
def Sum = new Connector({ A.Value + B.Value })
}
class Constant[T](x: T) extends Block {
def Result = new Connector({ x })
}
class Connector[T](f: => T) {
def Value: T = f
}
Run Code Online (Sandbox Code Playgroud)
出于类型安全原因,以下内容应该因类型异常而失败:
val const3 = new Constant("ping")
val const5 = new Constant("pong")
val block = new Arithmetic(const3.Result, const5.Result)
Run Code Online (Sandbox Code Playgroud)
您的问题可以通过以下方式重现:
class C[T: Numeric] {def add(a: T, b: T) = a+b }
error: type mismatch;
found : T
required: String
Run Code Online (Sandbox Code Playgroud)
那里发生了什么:在java中的scala中,你可以做String +任何东西,还有任何东西+ String.因为,与java不同,pperators只是普通的方法调用,这似乎意味着每种类型都有相应的+方法.当然,事实并非如此,因为java类型没有这样的方法.我们拥有的是implicit def any2StringAdd(x: Any)在Predef,这使得这个+可以通过隐式转换.在你的代码中,这是唯一的+可用,这就是为什么它抱怨B.Value不是String.
现在为什么+没有预定的?T:Numeric要求Numeric[T]隐式范围中有值.它没有说明T应该是什么类型,以及可用的方法T.这个Numeric[T]实例有一个def plus(x: T, y: T): T方法.只有这一点+在T 上没有.你可以直接打电话给加号,但这不方便.幸运的是,可以通过隐式转换添加+委托plus(就像+(String)在里面一样Predef),只要你在范围内加上一些含义:
import Numeric.Implicits._
Run Code Online (Sandbox Code Playgroud)