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の型推論のより厄介な制限の1つに遭遇しました!コンパイラがここで窒息している理由の明確な説明については、この回答を参照してください。

いくつかのオプションがあります。最も簡単に言うと、自分でタイプを指定するだけです。

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です。

于 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 に答える