1

考虑下面的例子,它应该打印 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
}

出于类型安全的原因,以下操作应该会失败并出现类型异常:

  val const3 = new Constant("ping")
  val const5 = new Constant("pong")

  val block = new Arithmetic(const3.Result, const5.Result)
4

2 回答 2

6

您的问题可以通过以下方式重现:

class C[T: Numeric] {def add(a: T, b: T) = a+b }
error: type mismatch;
found   : T
required: String

那里发生了什么:在scala中和java中一样,你可以做String +任何东西,也可以做任何东西+ String。因为,与 java 不同,perators 只是普通的方法调用,这似乎意味着每种类型都有一个对应的 + 方法。当然不是这样,因为java类型没有这样的方法。我们所拥有的是implicit def any2StringAdd(x: Any)in Predef,这使得它+可以通过隐式转换获得。在您的代码中,这是唯一可用的 + ,这就是为什么它抱怨B.Value不是String.

现在为什么预期+不可用?要求在隐式范围内T:Numeric有一个值。Numeric[T]它没有说明 T 应该是什么类型,以及在T. 这个Numeric[T]实例有一个def plus(x: T, y: T): T方法。仅此一项并不能+在 T 上使用。您可以直接调用 plus,但这并不方便。幸运的是,可以通过隐式转换添加+委托plus(就像+(String)was in一样Predef),前提是您将一些隐式放在范围内:

import Numeric.Implicits._
于 2011-10-10T14:52:25.533 回答
0

这有效:

class Arithmetic[ T <: Int] (val A: Connector[T], val B: Connector[T]) extends Block {
  def Sum = new Connector({ A.Value + B.Value })
}

数字没有+功能

于 2011-10-10T15:02:48.447 回答