假设:
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代码时遇到了这个问题,而且工作正常。
答案 0 :(得分:6)
你遇到了Scala类型推断的一个更烦人的限制!请参阅this answer,以清楚地解释编译器在这里窒息的原因。
你有一些选择。最简单的是你可以自己提供类型:
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
的界限中。
答案 1 :(得分:5)
它没有编译,因为T
没有出现在参数列表的任何地方,因此无法推断(或者更确切地说,推断为Nothing
)。
你可以这样解决:
def something [T] (foo : Class[_ <: Foo[T]]): T = foo.newInstance.get
答案 2 :(得分:0)
明确添加类型似乎有效:
scala> Baz.something[Bar,FooBar](classOf[FooBar])
res1: Bar = Bar@3bb0ff0
通常,当你得到一个Nothing
,你期望推断出其他类型时,意味着由于某种原因,编译器无法推断出该特定位置的类型。
那就是说,我提出了一个问题:我们如何重构代码以便推断出类型? @Régis的回答显示了解决方案。