假设我有以下特征来定义一个接口并采用几个类型参数……
trait Foo[A,B] { // implementation details not important }
我想使用伴侣对象作为特征的具体实现的工厂.我还想强制用户使用Foo接口而不是子类化所以我隐藏了伴随对象中的具体实现,如下所示:
object Foo { def apply[A,B](thing: Thing): Foo[A,B] = { ??? } private case class FooImpl[A1,B1](thing: Thing) extends Foo[A1,B1] private case class AnotherFooImpl[A2,B1](thing: Thing) extends Foo[A2,B1] }
我希望能够按如下方式使用工厂:
val foo = Foo[A1,B1](thing) // should be an instance of FooImpl val anotherFoo = Foo[A2,B1](thing) // should be an instance of AnotherFooImpl
解决方法
怎么样:
trait Foo[A,B] trait Factory[A,B] { def make(thing: Thing): Foo[A,B] } class Thing object Foo { def apply[A,B](thing: Thing)(implicit ev: Factory[A,B]) = ev.make(thing) private case class FooImpl[A,B](thing: Thing) extends Foo[A,B] private case class AnotherFooImpl[A,B] implicit val fooImplFactory: Factory[Int,String] = new Factory[Int,String] { override def make(thing: Thing): Foo[Int,String] = new FooImpl[Int,String](thing) } implicit val anotherFooImplFactory: Factory[String,String] = new Factory[String,String] { override def make(thing: Thing): Foo[String,String] = new AnotherFooImpl[String,String](thing) }
现在:
def main(args: Array[String]): Unit = { import Foo._ val fooImpl = Foo[Int,String](new Thing) val anotherFooImpl = Foo[String,String](new Thing) println(fooImpl) println(anotherFooImpl) }
产量:
FooImpl(testing.X$Thing@4678c730) AnotherFooImpl(testing.X$Thing@c038203)