scala 2.10:为什么有类型不匹配?

时间:2014-12-21 12:57:09

标签: scala

无法弄清楚这段代码有什么问题:

  trait NumberLike
  {
    def plus[T](a: T, b: T): T
  }

  class IntegerNumberLike extends NumberLike
  {
    def plus[Int](a: Int, b: Int): Int = 2 // type mismatch; found : scala.Int(2) required: Int
  }

但如果我这样做,它就有效:

  trait NumberLike[T]
  {
    def plus(a: T, b: T): T
  }

  class IntegerNumberLike extends NumberLike[Int]
  {
    def plus(a: Int, b: Int): Int = 2
  }

所以我有两个问题:

  • 为什么第一个代码示例不起作用?
  • 一般来说,何时应该使用类类型参数,何时应该使用方法类型参数?

2 个答案:

答案 0 :(得分:2)

方法中的类型参数与其他参数非常相似,实际参数的名称并不重要:plus[Int](a: Int, b: Int): Int plus[T](a: T, b: T): T完全相同

现在,很容易理解为什么plus[T](a: T, b: T): T = 2无法编译,不是吗?因为2不属于T类型。

关于你的第二个问题,很难准确回答,因为它相当广泛。简而言之,参数化类和方法分别定义了类或方法的模板。可以将其视为类/方法的系列,而不是单个对象。例如,代替plus[T] (a: T, b: T): T,可以写下:

def plus(a: Int, b: Int): Int
def plus(a: Long, b: Long): Long
def plus(a: Double, b: Double): Double

或者,您可以拥有:

而不是class NumberLike[T]
class IntLike
class LongLike
class DoubleLike

以这种方式看待你,你可以问自己一个问题,你在设计什么:它是一个类的家庭还是一系列方法?回答这个问题会告诉你是否应该对一个类,一个方法或两者进行参数化...考虑:

class Iterable[+A] {
    ...
    def def reduceLeft[B >: A](op: (B, A) ⇒ B): B
    ...
}

答案 1 :(得分:1)

定义:

def plus[Int](a: Int, b: Int): Int

相当于

def plus[T](a: T, b: T): T

例如,您可以通过以下示例更清楚地看到它:

  type Int = String

  def main(args: Array[String]) {
    val x: Int = "foo"
    println(x)
  }

你没有错误,打印“foo”。由于您只是将参数类型重命名为Int(而不是T)。这就是编译器抱怨Int(在这种情况下是2的值)和Int(你的参数类型名称)不一样的原因。我不知道你是否可以为参数定义中的特定类型实现加号功能。如果参数适用于所有类,则使用类类型参数;如果参数仅适用于该方法,则使用方法参数。这只是方法的可见性和责任问题。