5

鉴于:

class Foo[T] {
 def get: T
}

class Bar
class FooBar extends Foo[Bar] {
 def get = new Bar
}

object Baz {
    def something [T, U <: Foo[T]] (foo : Class[U]): T = foo.newInstance.get
}

我应该能够做这样的事情,对吧?

Baz.something(classOf[FooBar])

奇怪的是,这是抛出:

inferred type arguments [Nothing,this.FooBar] do not conform to method something's type parameter bounds [T,U <: this.Foo[T]]

这很奇怪:S。顺便说一句,我在迁移一些与我在这里编写的代码等效的 Java 代码时遇到了这个问题,并且运行良好。

4

3 回答 3

6

您遇到了 Scala 类型推断的更烦人的限制之一!请参阅此答案,以清楚地解释为什么编译器在这里阻塞。

你有几个选择。最简单的是,您可以自己提供类型:

Baz.something[Bar, FooBar](classOf[FooBar])

但这太冗长了。如果你真的不关心U,你可以把它排除在类型参数列表之外:

object Baz {
  def something[T](foo: Class[_ <: Foo[T]]): T = foo.newInstance.get
}

现在FooBar将在您的示例中正确推断。您还可以使用上面链接的答案中讨论的技巧:

object Baz {
  def something[T, U <% Foo[T]](foo: Class[U]): T = foo.newInstance.get
}

为什么这个工作有点棘手——关键是在视图绑定被脱糖后,T不再出现在U's 绑定中。

于 2012-10-18T19:04:58.507 回答
5

它不会编译,因为T它没有出现在参数列表中的任何位置,因此无法推断(或者更确切地说,它被推断为Nothing)。

你可以像这样修复它:

def something [T] (foo : Class[_ <: Foo[T]]): T = foo.newInstance.get
于 2012-10-18T19:03:10.787 回答
0

显式添加类型似乎有效:

scala> Baz.something[Bar,FooBar](classOf[FooBar])
res1: Bar = Bar@3bb0ff0

通常,当您得到一个Nothing您期望推断出其他类型的位置时,意味着由于某种原因编译器无法推断出该特定位置的类型。

也就是说,我提出一个问题:我们如何重构代码以便推断出类型?@Régis 的回答显示了解决方案。

于 2012-10-18T19:03:25.950 回答