はい、消去された土地に自分自身が見つかりました。第一ケース(オリジナルコード)で
、コンパイラはあなたが指定していない場合A
(この例ではBase
である、Foo
ですが、実行時に型パラメータが上限タイプに消去されていることを知っています上型バインドでは、型パラメータはObject
まで消去されます)。次のようにJVMが(何の種類のパラメータに気付かない)あなたのコードを見て:
def checker(func: Base => String): Base => String =
(b: Base) => b match {
case a : Base => func(a)
case _ => "error"
}
どれFoo
またはBar
オブジェクトがBase
にマッチします、その後、JVMはFoo
にキャストしようとfunc
を呼び出します。 b
がクラスFoo
のオブジェクトである場合に動作しますが、Bar
のキャスト例外がスローされます。驚く様な事じゃない。
2番目のケースでは、タイプパラメータを削除し、の代わりにA
をFoo
に置き換えます。checker
だから、実行時に、あなたのコードは、この(関数はそもそもパラメータ化タイプではないので、何も消去されていない)のようになります。
def checker(func: Foo => String): Base => String =
(b: Base) => b match {
case a: Foo => func(a)
case _ => "error"
}
これは期待通りに動作しますが、それはFoo
のためにのみチェックに固定されています。したがって、Bar
と別のタイプのテスト用に別々のchecker
を書く必要があります。
3番目のケースでは、typeパラメータは保持していますが、関数の引数を省略し、を"good"
に置き換えます。これにより、func
が呼び出されないので、Foo
へのキャストは必要ないので、ケース1(同様に、消去はFoo
からBase
まで)と同様のコードになります。したがって、例外はありません。
def checker: Base => String =
(b: Base) => b match {
case a: Base => "good"
case _ => "error"
}
は、単にあなたが(ベースのサブクラス)を渡す任意のオブジェクトが最初の句で一致していると
checker
は常に「『良い』」を返します。
今すぐ解決してください。あなたはManifest
で正しい軌道に乗っていました(しかし、あなたが示したコードは、あなたが達成しようとしているものにとってはあまりにも複雑です)。 Manifest
Scalaコンパイラは、実行時に消去された型を '回復'するためにメソッド/関数に追加のオブジェクトを渡します。私は 'context bound'を使用する代わりに、(implicit manifest : Manifest[A])
と綴るのではなく、同じです。
def checker[A <: Base: Manifest](func: A => String): Base => String =
(b: Base) => if(manifest[A].erasure == b.getClass) func(b.asInstanceOf[A])
else "error"
あなたはこのようにそれを呼び出すときそれでは:
def fooFunc(f: Foo) = "It's a foo"
def barFunc(f: Bar) = "It's a bar"
def main(arg: Array[String]) {
val check1 = checker(fooFunc)
val check2 = checker(barFunc)
println(check1(new Foo) + ", " + check1(new Bar))
println(check2(new Foo) + ", " + check2(new Bar))
}
期待どおりの出力が得られます:
It's a foo, error
error, It's a bar
消去はScalaでは楽しいのすべての種類のソースでありますここでの型パラメータ化はJavaよりも一般的です。それを回避する方法はありません、私はあなたができることについてすべてを学ぶことをお勧めします。
いいえ、それは役に立ちません。これは例外を取り除きますが、FooとBarの両方に対して「良い」と表示します。 問題は、チェックでタイプAが何かを忘れているようです。 –
すみません。更新された答えを見る、確かにFoo&Barを印刷する。あなたが何をしようとしているのかわからない、あなたが現在使っているコードであなたの質問を更新する必要があるので、自分自身と他の人があなたの話を知っているでしょう(例えば、 "まだ良いものをプリントしていますか?") – virtualeyes
不明。チェッカーの目的は、1つを除くすべてのタイプを排除することです。結果が「Foo、Bar」の場合は、FooとBar引数の両方にビールAが認識されていることを意味します。見たいのは「Foo、error」です。 –