0

コンストラクターのパラメーターとして対応するインスタンスItemをそれぞれ必要とする s のクラス階層があります。次のように使用して、サブクラスを型パラメーターとして指定しItemTemplateてインスタンス化するジェネリック関数を作成したいと思います。ItemItemItemTemplate

val newItem = instantiateItem[ItemClass, TemplateClass](templateInstance)

少し研究した後、私は今持っています

def instantiateItem[I, T](implicit mf: Manifest[I], template: T): I = {
    val constructor = mf.erasure.getConstructor(classOf[T])
    constructor.newInstance(template).asInstanceOf[I]
}

しかし、これはコンパイルされませんclassOf[T]。エラーが発生します

クラス タイプが必要ですが、T が見つかりました

に置き換えclassOf[T]てみましたclassManifest[CM].erasureが、CM は にコンテキストをバインドする必要があるため、これは機能しませんClassManifest。明らかに、バインドされた型パラメーターを暗黙のパラメーターで使用することはできません。

私がここでやりたいことをすることは可能ですか?

4

2 に答える 2

1

コードを次のように修正すると、うまくいくはずです。

def instantiateItem[I : Manifest, T <: AnyRef : Manifest](template: T): I = {
    val constructor = manifest[I].erasure.getConstructor(manifest[T].erasure)
    constructor.newInstance(template).asInstanceOf[I]
}

I : Manifest構文は、暗黙的なパラメーターの推奨されるシュガーレッド バージョンです。

ManifestScala 2.10は非推奨になるので注意してください。TypeTag

于 2012-08-11T15:41:30.640 に答える
1

templateを呼び出すだけでクラスを取得できますtemplate.getClasstemplateのサブタイプである必要があるAnyRefため、 にキャストするAnyRef(プリミティブ型のボックス化を強制する) か、 の上限を追加しますT

def instantiateItem[I, T <: AnyRef](implicit mf: Manifest[I], template: T): I = {
  val constructor = mf.erasure.getConstructor(template.getClass)
  constructor.newInstance(template).asInstanceOf[I]
}

質問のコードで示されているように、明示的に渡したい場合はtemplate、暗黙的な引数と明示的な引数を分離する必要があります。

def instantiateItem[I, T <: AnyRef](template: T)(implicit mf: Manifest[I]): I = {
  val constructor = mf.erasure.getConstructor(template.getClass)
  constructor.newInstance(template).asInstanceOf[I]
}

別名

def instantiateItem[I : Manifest, T <: AnyRef](template: T): I = {
  val mf = implicitly[Manifest[I]]
  val constructor = mf.erasure.getConstructor(template.getClass)
  constructor.newInstance(template).asInstanceOf[I]
}

一般に、可能であれば、慎重に設計することでリフレクションを使用する必要をまったく回避できます。

trait ItemCompanion[I,T] {
   def instantiateItem(template: T): I
}

object TestItem extends ItemCompanion[TestItem, TestTemplate] {
   implicit def self: ItemCompanion[TestItem, TestTemplate] = this
   def instantiateItem(template: TestTemplate): TestItem = new TestItem(template)
}
class TestItem(template: TestTemplate)
trait TestTemplate

// try out
def instantiateItem[I, T](implicit ic: ItemCompanion[I, T], t: T): I =
   ic.instantiateItem(t)

implicit val temp: TestTemplate = new TestTemplate {}
instantiateItem[TestItem, TestTemplate]
于 2012-08-11T15:37:30.880 に答える