如何在scala中的泛型方法中创建特征实例?

时间:2010-07-18 04:15:39

标签: scala new-operator instance traits

我正在尝试使用此方法创建特征实例

val inst = new Object with MyTrait

这很好用,但我想把这个创作转移到生成器函数,即

object Creator {
  def create[T] : T = new Object with T
}

我显然需要清单以某种方式修复类型擦除问题,但在此之前,我遇到了两个问题:

  1. 即使有隐式清单,Scala仍然要求T是一个特征。如何添加限制以创建[T]以使T成为特征?

  2. 如果我选择使用Class.newInstance方法动态创建实例而不是使用“new”,我如何在“new object with T”中指定“with”?是否可以在运行时动态创建新的具体mixin类型?

2 个答案:

答案 0 :(得分:15)

我不确定您的问题的动机是什么,但您可以考虑将T的工厂作为隐含参数传递。这称为使用类型 ad-hoc多态

object Test extends Application {
  trait Factory[T] {
    def apply: T
  }
  object Factory {
    /**
     * Construct a factory for type `T` that creates a new instance by
     * invoking the by-name parameter `t`
     */
    def apply[T](t: => T): Factory[T] = new Factory[T] {
      def apply = t
    }
  }

  // define a few traits...
  trait T1
  trait T2

  // ...and corresponding instances of the `Factory` type class.
  implicit val T1Factory: Factory[T1] = Factory(new T1{})
  implicit val T2Factory: Factory[T2] = Factory(new T2{})

  // Use a context bound to restrict type parameter T
  // by requiring an implicit parameter of type `Factory[T]`
  def create[T: Factory]: T = implicitly[Factory[T]].apply

  create[T1]
  create[T2]

}

另一方面,您可以在运行时调用编译器,详见this answer中的问题“Scala中的动态混合 - 是否可能?”。

答案 1 :(得分:8)

你不能这样做(即使是Manifest)。代码new Object with T涉及创建表示Object with T组合的新匿名类。要将它传递给create函数,您必须在运行时生成这个新类(使用新的字节码),并且Scala没有在运行时生成新类的工具。

一种策略可能是尝试将工厂方法的特殊功能转移到类的构造函数中,然后直接使用构造函数。

另一种可能的策略是为您感兴趣使用此类的特征创建转换函数(隐式或其他)。