无法弄清楚这段代码有什么问题:
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
}
所以我有两个问题:
答案 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(你的参数类型名称)不一样的原因。我不知道你是否可以为参数定义中的特定类型实现加号功能。如果参数适用于所有类,则使用类类型参数;如果参数仅适用于该方法,则使用方法参数。这只是方法的可见性和责任问题。