8

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

val inst = new Object with MyTrait

这很好用,但我想将此创建移到生成器函数中,即。

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

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

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

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

4

2 回答 2

15

我不确定您提出问题的动机是什么,但您可以考虑将工厂T作为隐式参数传递。这称为使用类型类临时多态性

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]

}

在光谱的另一端,您可以在运行时调用编译器,如对“Scala 中的动态混合 - 是否可能?”问题的回答中所详述。

于 2010-07-18T06:21:05.373 回答
8

你不能这样做(即使有清单)。该代码new Object with T涉及创建一个新的匿名类,该类表示Object with T. 要将其传递给您的create函数,您必须在运行时生成这个新类(带有新字节码),而 Scala 没有在运行时生成新类的工具。

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

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

于 2010-07-18T04:28:25.177 回答