【问题标题】:How do I create an instance of a trait in a generic method in scala?如何在 scala 的泛型方法中创建特征的实例?
【发布时间】:2011-03-17 12:00:31
【问题描述】:

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

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 类型?

【问题讨论】:

    标签: scala new-operator instance traits


    【解决方案1】:

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

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

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

    【讨论】:

    • 这似乎是该语言的一个有趣限制,但我看不出为什么它不能通过 Scala 中的新“动态”混合支持来修复。特征代码已经作为静态方法可用,因此线性化查找可以在运行时计算,而不是嵌入到类字节码中。然后你只需要添加运行时类型检查,这样“asInstanceOf”就可以工作了。
    【解决方案2】:

    我不确定您提出问题的动机是什么,但您可以考虑将 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 中的动态混合 - 是否可能?”问题的详细说明。

    【讨论】:

    • 谢谢,我可能不得不使用这种方法。我的用例是 Java 代理。我想写一个可远程的库。因此,我需要为我的所有类定义接口,这很痛苦,因为我想公开所有内容。一种解决方案是将所有内容编写为特征,然后我免费获得接口定义。 create 函数的目的是在代理连接的“具体”端实例化一个特征。
    猜你喜欢
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    相关资源
    最近更新 更多