scalaフォーラムでこの投稿に出くわしました。
ここに要約があります:
Scala コンパイラがワイルドカードの型境界を「引き継ぐ」ようには見えないことに気付きました。
scala> class Foo { def foo = 42 }
defined class Foo
scala> class Bar[A <: Foo](val a: A)
defined class Bar
scala> def bar(x: Bar[_]) = x.a.foo
:7: error: value foo is not a member of Any
メソッド bar の正確な型パラメーターはメソッドでは重要ではありませんが、メソッド bar のパラメーターは依然として Foo によって上限が設定されていると予想されます。この動作には特定の理由がありますか?
その後、議論は仕様解釈の論争に入ります:)
説明?
最終的に、ポスターはこの説明を提案します:
ただし、コンパイラが Bar[_] に対してこれを行った場合、一貫性の理由から、Bar[A] に対しても行う必要があります。ただし、後者はいくつかの奇妙な結果をもたらします。たとえば、 def bar[A](x: Bar[A], y: Bob[A]) は突然、ボブにバインドされた暗黙の型を運ぶ必要があります。Bob が独自のタイプ バインドを持っていると、非常に面倒になります。
わからない理由
def bar[A](x: Bar[A])
Bar 型パラメーターが制限されているため、単独ではコンパイルできません。
とにかく、私は次のことが完全に理にかなっていると信じています:
def bar(x: Bar[_], y : Bob[_])
回避策
彼らが提案する回避策として:
def bar(x: Bar[_ <: Foo]) = x.a.foo
DRYではないことに加えて、物事が難しくなります。
ツリーを考えてみましょう
abstract class Tree[T <: Tree[T]] { val subTree : List[T] }
ツリーを再帰的に通過する関数 (明らかに Tree クラスの外部で定義される) をどのように定義しますか。
def size( tree : Tree[_] ) = tree.subTree.size + tree.subTree.map(size(_)).sum
subTree は List[Any] に変換されるため、明らかに機能しません。そのため、型パラメーターが必要です。
def size[T <: Tree[T]]( tree : T ) = ...
さらに醜い:
class OwnATree( val myTree : Tree[_] ){}
なるはず
class OwnATree[T <: Tree[T]]( val myTree : T ){}
などなど...
どこかに何か問題があると思います:)