假设我创建了一个单参数泛型方法:
trait MyTrait[T] {
def method():T
}
然后将其扩展并参数化。:
class MyClass extends MyTrait[java.lang.String] {
def method() = "foo"
}
等于:
class MyClass extends MyTrait[String] {
def method() = "foo"
}
但是,当您创建一个trait方法,将lambda参数化时,如下所示:
trait MyTrait {
def apply[T](input:()=>T):T
}
那你就没那么幸运了。:
class MyClass extends MyTrait {
def apply(input:()=>java.lang.String) = "foo"
}
将导致这个:
Error:(25, 45) type mismatch;
found : java.lang.String("foo")
required: String
def apply[String](input:()=>String) = "foo"
^
然而,这是好的:
class MyClass extends MyTrait {
def apply[String](input:()=>String) = new String("foo")
}
那么在什么情况下scalac实际上知道需要进行转换,在什么情况下它不知道?
此外,即使我写出java.lang.String类型
的整个路径class MyClass extends MyTrait {
def apply[java.lang.String](input:()=>java.lang.String) = new java.lang.String("foo")
}
抛出另一个错误:
Error:(25, 21) ']' expected but '.' found.
def apply[java.lang.String](input:()=>java.lang.String) = new java.lang.String("foo")
^
如果我想直接通过模板化java.lang.String来实现后一种方式,我该怎么做呢?
This
class MyClass extends MyTrait {
def apply[String](input:()=>String) = new String("foo")
}
不是很好。结果是class type required but String found
。这里的问题是,当您使用参数化方法扩展类时,您没有声明类型参数是什么。在使用该方法时声明它。
让我们重写一下:
class MyClass extends MyTrait {
def apply[String](input:()=>String) = input()
}
现在观察:
scala> (new MyClass).apply[String](() => "foo")
res0: String = foo
scala> (new MyClass).apply[Int](() => 5)
res1: Int = 5
之所以有效,是因为当你声明this:
def apply[String](input:()=>String) = input()
String
为参数的名称。如果你写T
, Xyzzy
,或ManISuckAtTypeParameters
而不是上面的String
,它将是完全相同的事情。您说您将获得一个类型参数,您将命名类型参数String
,这是返回函数的值,并且通过覆盖apply
方法。
当我调用apply[Int](() => 5)
时,Scala将用Int
替换定义中的 String
。