1

オブジェクトのフィールド/メソッドをどのように型にバインドしますか?

私はやろうとしています:

object CRUDable {

  private val allCRUDables = scala.collection.mutable.Map[String, CRUDableMeta[_]]()
  def add(crudable: CRUDableMeta[_]) { allCRUDables += (crudable.name -> crudable) }

そして私のコンパイラは次のように言っています:

type arguments [_$5] do not conform to trait CRUDableMeta's type parameter bounds [T <: etam.jpa.crud.CRUDable[T]]

あらゆるタイプの CRUDableMeta[_] を受け入れる Map が必要です。

前もってありがとう、イータム。

4

1 に答える 1

0

私は CRUD を知らず、役割を果たさないため、自由に一般的なケースを構築しています。

trait Data[T]
trait Meta[T <: Data[T]] { def name: String }
val all = collection.mutable.Map[String, Meta[_]]()

これで、コンパイラは何が問題なのかを正確に教えてくれます

def add(c: Meta[_]) { all += c.name -> c }

それは言います:

error: type arguments [_$1] do not conform to trait
       Meta's type parameter bounds [T <: Data[T]]

そのため、Scala ではMap文句を言わずに を構築できますが (正直なところ理由はわかりません)、実際に値をマップに格納しようとすると、Metaの型パラメーターの境界に遭遇します。T

解決策は、次のいずれかの形式を使用することです。(1) メソッドの型パラメータ:

def add[T <: Data[T]](c: Meta[T]) { all += c.name -> c }

(2) 存在型

def add(c: Meta[T] forSome { type T <: Data[T] }) { all += c.name -> c }

(2) について私に尋ねないでください。私は存在型が何であるかを忘れ続けています... (1) と (2) のどちらが優れているかについて、他の誰かがここで洞察を提供できるかもしれません。(関連する質問への唯一の回答は、(1) と (2) がほとんど同じであることを示唆しています。さらに、(1) を使用すると、後で type を参照できますT。ここでは必要ありませんが、それでもより読みやすいバージョンです。 、私は言うだろう)

于 2012-06-19T00:08:46.050 に答える