template
を呼び出すだけでクラスを取得できますtemplate.getClass
。template
のサブタイプである必要がある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]