理想的には、Scala で次のことができるようにしたいと考えています。
import Builders._
val myBuilder = builder[TypeToBuild] // Returns instance of TypeToBuildBuilder
val obj = myBuilder.methodOnTypeToBuildBuilder(...).build()
原則として、目標は単純に、外部マッピング定義を使用して(つまり、これらのクラスを変更できないと仮定して) 'マップ'TypeToBuild
し、これを型推論に活用できるようにすることです。TypeToBuildBuilder
AnyRef
タイプで次の作業を行いました:
import Builders._
val myBuilder = builder(TypeToBuild)
myBuilder.methodOnTypeToBuildBuilder(...).build()
object Builders {
implicit val typeToBuildBuilderFactory =
new BuilderFactory[TypeToBuild.type, TypeToBuildBuilder]
def builder[T, B](typ: T)(implicit ev: BuilderFactory[T, B]): B = ev.create
}
class BuilderFactory[T, B: ClassTag] {
def create: B = classTag[B].runtimeClass.newInstance().asInstanceOf[B]
}
型は、型引数ではなく関数引数として渡されることに注意してください。
Any
上記を型だけでなく、型で動作させる方法を見つけるだけでも、私は非常に満足していAnyRef
ます。Singleton 型は s に対してのみサポートされているためAnyRef
(つまり、TypeToBuild.type の使用)、この制限が発生しているようです。
そうは言っても、元の「理想的な」シナリオ (関数引数の代わりに型引数を使用) を解決する答えは素晴らしいでしょう!
編集
必要な可能な解決策classOf[_]
(使用する必要がないのが本当に大好きclassOf
です!):
import Builders._
val myBuilder = builder(classOf[TypeToBuild])
myBuilder.methodOnTypeToBuildBuilder(...).build()
object Builders {
implicit val typeToBuildBuilderFactory =
new BuilderFactory[classOf[TypeToBuild], TypeToBuildBuilder]
def builder[T, B](typ: T)(implicit ev: BuilderFactory[T, B]): B = ev.create
}
class BuilderFactory[T, B: ClassTag] {
def create: B = classTag[B].runtimeClass.newInstance().asInstanceOf[B]
}
ただ使用できるということbuilder(TypeToBuild)
は、エレガンス/簡潔さの勝利です。builder[TypeToBuild]
おそらくこれはいつか機能する可能性があるため、使用できることはクールです(Scalaの型推論の進歩により):
val obj: TypeToBuild = builder.methodOnTypeToBuildBuilder(...).build();
classOf
以下は、http : //ideone.com/94rat3を使用した完全な実際の例です。