【问题标题】:Scala trait with generic self type具有通用自我类型的 Scala 特征
【发布时间】:2015-12-22 22:09:52
【问题描述】:

我有一个特征,它定义了一个动作,它是 .copy() 的美化版本。看起来像这样:

trait Optimize[T] {
    def optimize: T
}

还有一堆扩展它的类,比如:

case class Account(field: String) extends Optimize[Account] {
    def optimize = this.copy(field = field.intern())
}

有没有一种方法可以定义一个特征,该特征需要方法 optimize 返回与 self 相同的类型,但在扩展它时不需要指定类型?所以我可以写:

case class Account(field: String) extends Optimize {
    def optimize = this.copy(field = field.intern())
}

【问题讨论】:

  • 另一种方法是将其拆分为隐式样式,因此 optimize : T => T 不是成员,而是当您在范围内有 Optimize[T] 时可以在 T 上使用它。那么就没有什么有趣的事情返回不同的类型了

标签: scala generics


【解决方案1】:

简短回答:你不能。

需要以一种或另一种方式(抽象类型)告诉Optimize 该函数的返回类型是什么。

为什么?因为Optimize 可以在类型表达式中使用而无需指定具体类,并且编译器无法知道它会生成什么类型​​:

def someOtherMethod (a: Optimize) {
  val result = a.optimize // what is the type?
}

(在抽象类型的情况下,返回类型将是a.TOptimize#T ... 不是很有用)

【讨论】:

  • 谢谢,显然不能。我想这样做只是因为编写类“A extends Trait [A]”感觉很奇怪,我认为有办法避免它。 sd 我一开始在考虑类型类,它看起来是一般来说这个任务的最佳解决方案之一。但在我的特殊情况下,这些优化方法将具有其他可优化的字段,并且会增加太多混乱。 F-bounds 对我没有帮助,因为我仍然必须指定类型。在 case class 中指定类型只是将这个声明移动到某个地方。
【解决方案2】:

如果您只想避免在扩展时指定类型参数,则可以将定义移动到这样的类型成员中。

trait Optimize {
    type T
    def optimize: T
}

case class Account(field: String) extends Optimize {
    type T = Account
    def optimize = this.copy(field = field.intern())
}

但你只是把它从一个地方移到另一个地方。此外,使用类型参数对 trait 进行参数化比让类型成员参与进来要好得多。

这样做的原因是什么?因为您的用例对于类型参数来说似乎是一个完全有效的情况。需要通过类型参数或类型成员告诉特征优化()返回的是什么。

【讨论】:

    【解决方案3】:

    你可以使用this.type作为返回值来引用实现者的类型。

    def optimize: this.type = ???
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多