我有一个特征,它定义了一个动作,它是 .copy() 的美化版本。看起来像这样:
trait Optimize[T] {
def optimize: T
}
以及一堆扩展它的类,例如:
case class Account(field: String) extends Optimize[Account] {
def optimize = this.copy(field = field.intern())
}
有没有一种方法可以定义一个特征,要求方法优化返回与 self 相同的类型,但在扩展它时不需要指定类型?这样我就可以写:
case class Account(field: String) extends Optimize {
def optimize = this.copy(field = field.intern())
}
您可以使用
this.type
作为返回值来引用实现者的类型。
def optimize: this.type = ???
简短回答:你不能。
无论怎样(抽象类型),您需要告诉
Optimize
该函数的返回类型是什么。
为什么?因为
Optimize
可以在类型表达式中使用而无需指定具体类,并且编译器无法知道它将生成什么类型:
def someOtherMethod (a: Optimize) {
val result = a.optimize // what is the type?
}
(在抽象类型的情况下,返回类型将是
a.T
或 Optimize#T
...不是很有用)
如果您只想避免在扩展时指定类型参数,则可以将定义移至类型成员,如下所示。
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 优化()返回的是什么。
有这样的事吗?
trait Ret[T]
trait A {
def func(): Ret[_ <: A]
}
case class B() extends A {
override def func(): Ret[B] = ???
}
除了阿尔瓦罗所说的之外,我认为你的特质的一个问题是没有什么可以阻止一个人这样做:
case class Account(field: String) extends Optimize[Int] {
def optimize: Int = 42
}
您可能不打算允许这一点。为了防止这种情况,我认为你必须这样做:
trait Optimize[T <: Optimize[T]] {
def optimize: T
}
这确保了一个类只能扩展自身的
Optimize
。