在什么情况下scala可以正确地将String转换为java.lang.String ?



假设我创建了一个单参数泛型方法:

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

最新更新