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

时间:2016-07-03 06:11:25

标签: java string scala templates generics

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

trait MyTrait[T] {
  def method():T
}

然后扩展它并进行参数化。这样:

class MyClass extends MyTrait[java.lang.String] {
  def method() = "foo"
}

与此相同:

class MyClass extends MyTrait[String] {
  def method() = "foo"
}

但是,当你创建一个特征参数化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以后一种方式实现它,我将如何去做呢?

1 个答案:

答案 0 :(得分:3)

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

这是有效的,因为当你宣布这个时:

  def apply[String](input:()=>String) = input()

String参数的名称。如果您在上面写了TXyzzyManISuckAtTypeParameters而不是String,那将是完全相同的。您说您将获得一个类型参数,您将命名类型参数String,并且这是返回函数的值,并且覆盖apply方法。

当我致电apply[Int](() => 5)时,Scala会在String的定义中替换 Int