2011-09-13 7 views
2

私の構造が取ることができるものに柔軟性を与えるために、上の型の境界を使用するのが本当に好きです。私は私のクラスは限りそれは一貫性のあるようServiceのサブクラスを使用することができることをしようとしているスカラの上限型の境界と親クラス

object BoundsTest { 
    abstract trait Service 
    class Collection[T <: Service] extends collection.mutable.HashMap[Symbol, collection.mutable.Set[T]] with collection.mutable.MultiMap[Symbol, T] 
    type Actives[T <: Service] = collection.mutable.HashMap[Symbol, T] 
    class Library[T <: Service](collection: Collection[T], actives: Actives[T]) 
    private val libraries = new collection.mutable.HashMap[Symbol, Library[Service]] 
    def setLibrary[T <: Service](name: Symbol, library: Library[T]) { 
    libraries += name -> library 
    } 
} 

:私は次のコードで見つけしかし、私は本当にそれの原理のいずれかを知りません。しかし、これは動作しません:

$ scalac test.scala 
test.scala:10: error: type mismatch; 
found : com.bubblefoundry.BoundsTest.Library[T] 
required: com.bubblefoundry.BoundsTest.Library[com.bubblefoundry.BoundsTest.Service] 
Note: T <: com.bubblefoundry.BoundsTest.Service, but class Library is invariant in type T. 
You may wish to define T as +T instead. (SLS 4.5) 
    libraries += name -> library 
         ^

問題は、私はどのように、考えて、私はすべてが正常にコンパイル次のように変更しますかのように私は、librariesを定義する(いつ?):

// private val libraries = new collection.mutable.HashMap[Symbol, Library[Service]] 
def setLibrary[T <: Service](name: Symbol, library: Library[T]) { 
    new collection.mutable.HashMap[Symbol, Library[T]] += name -> library 
} 

libraries HashMapにの複数の値がServiceであるように宣言するにはどうすればよいですか?ここでServiceを参照することは可能ですか、それは不可能ですか?

または間違ったツリーを完全に吠えていますか?ありがとう!

答えて

9

Scalaでは、パラメータ化された型はデフォルトでは不変です(例: Cage[A]については、Cage[Bird]は、ではなく、であり、Cage[Animal]である。しかし、変数の宣言を使用して、型を共変または反変にすることができます。 Cage[+A](a: A)これは、コンパイラがエラーメッセージであなたに伝えようとしているものです。

ここで、型パラメータを共変えることは必ずしも可能ではありません。これは、型変数がいわゆる正の発生でのみ使用される場合にのみ機能します。あなたのクラスが不変の場合は、別の(100%ではない)方法を入れてください。あなたの場合、それは動作します。だから、あなたがしなければならないすべてはLibraryの定義に+を追加することです:コンパイルエラーとして

class Library[+T <: Service](collection: Collection[T], actives: Actives[T]) 
4

親切クラスLibraryは不変である、と言います。それは次のとおりです。S <: T

IFF

Library[S] <: Library[T]保持していません。このプロパティは共分散と呼ばれ、ジェネリック型パラメータのプロパティです。これは、コンパイラエラーを引き起こしている理由は、あなたの地図には、その値の型としてLibrary[Service]を期待していることであり、あなたがLibrary[T]を追加しようとしている(これは、共分散の欠如にもT <: Serviceかかわらず、Library[Service]されていない、)

Libraryクラスが不変の場合、タイプパラメータに+を追加して、scalacにライブラリがそのタイプで共変なであることを示すことができるはずです。