用Scala实例化一个通用类型的具体类

3

我有一个通用的特性,其代码如下:

trait MyTrait[T] {
  def doSomething(elems: Seq[T])
}

我有一个对象工厂,它的定义如下:

object MyTraitFactory {
  def apply[T](param1: Boolean, param2: Boolean): MyTrait[T] = {
    // based on the type of T, I would like to instantiate sub types
  }
}

我已经有一些具体的实现,例如:

class MyStringTrait extends MyTrait[String]

class MyIntTrait extends MyTrait[Int]

现在我需要一个神奇的位,它可以在我的对象工厂中查找类型并实例化相应的实现。有什么建议吗?

1个回答

4

可以使用隐式类型类在scala中解决这个问题。创建一个工厂特质,并为每种类型创建具体的实现:

object MyTraitFactory {

  def apply[T](param1: Boolean, param2: Boolean)(implicit factory: MyTraitCreator[T]): MyTrait[T] = {
    // call the typeclass create method
    factory.create(param1, param2)
  }

  // factory trait
  trait MyTraitCreator[T] {
    def create(param1: Boolean, param2: Boolean): MyTrait[T]
  }

  // provide an implicit factory object for the specific types:
  object MyTraitCreator {

    implicit object MyStringTraitCreator extends MyTraitCreator[String] {
      override def create(param1: Boolean, param2: Boolean): MyTrait[String] = {
        // create the String type here
        new MyStringTrait
      }
    }

    implicit object MyIntTraitCreator extends MyTraitCreator[Int] {
      override def create(param1: Boolean, param2: Boolean): MyTrait[Int] = {
        // create the Int type here
        new MyIntTrait
      }
    }
  }
}

Scala通过隐式参数来“隐藏”类型类。但为了使其工作,您必须确保将隐式工厂对象放在编译器寻找隐式的位置(例如上面的MyTraitCreator的伴生对象)。该模式即使没有implicit也能很好地工作,但然后需要调用者在每次调用时提供具体工厂。
该解决方案包括大量样板代码,但在编译时静态工作,并且不会受到类型擦除的影响。Scala甚至带有语法糖:
def apply[T: MyTraitCreator](param1: Boolean, param2: Boolean): MyTrait[T] = {
    // call the typeclass create method
    implicitly[MyTraitCreator[T]].factory.create(param1, param2)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接