1

理想的には、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を使用した完全な実際の例です。

4

3 に答える 3