Scala 覆盖可堆叠特征模式中的抽象类型成员
假设我们想要定义如何在某些数据上累积结果的方法:Scala 覆盖可堆叠特征模式中的抽象类型成员,scala,traits,abstract-type,Scala,Traits,Abstract Type,假设我们想要定义如何在某些数据上累积结果的方法: case class Data(x: Int, y: Int) 我们定义了这样做的特征: trait Accumulator { type R def add(acc: R, d: Data): R def zero: R } 以及一个简单的实现: trait XAccumulator extends Accumulator { type R = Int def add(acc: Int, d: Data) = ac
case class Data(x: Int, y: Int)
我们定义了这样做的特征:
trait Accumulator {
type R
def add(acc: R, d: Data): R
def zero: R
}
以及一个简单的实现:
trait XAccumulator extends Accumulator {
type R = Int
def add(acc: Int, d: Data) = acc + d.x
def zero = 0
}
我想使用stackable trait模式来使用这些简单累加器中的多个:
trait TraceYAccumulator extends Accumulator {
abstract override type R = (Seq[Int], super.R)
// fails:
// `abstract override' modifier not allowed for type members
def add(acc: R, d: Data) = {
val r = super.add(acc._2, d)
(acc._1 :+ d.y, r)
}
def zero = (Seq.empty[Int], super.zero)
}
显然,我不允许重写抽象类型成员。如何使用stackable trait模式更改被重写方法的结果类型
我的第二种方法是使用类型参数:
trait Accumulator[R] {
def add(acc: R, d: Data): R
def zero: R
}
trait XAccumulator extends Accumulator[Int] {
def add(acc: Int, d: Data) = acc + d.x
def zero = 0
}
但现在它变得非常奇怪:
trait TraceYAccumulator[T] extends Accumulator[(Seq[Int], T)] {
this: Accumulator[T] =>
def add(acc: (Seq[Int], T), d: Data): (Seq[Int], T) = {
val r = this.add(acc._2, d)
// fails: overloaded method value add with alternatives:
// (acc: (Seq[Int], T),d: Data)(Seq[Int], T) <and>
// (acc: _14695,d: Data)_14695 cannot be applied to (T, Data)
(acc._1 :+ d.y, r)
}
def zero: (Seq[Int], T) = (Seq.empty[Int], this.zero)
}
trait tracey累加器[T]扩展累加器[(Seq[Int],T)]{
此:累加器[T]=>
def add(附件:(序号[Int],T),d:数据):(序号[Int],T)={
val r=此添加(根据2,d)
//失败:重载方法值添加选项:
//(附件:(序号[Int],T),d:数据)(序号[Int],T)
//(acc:_14695,d:数据)_14695不能应用于(T,数据)
(附件1:+d.y,r)
}
定义零:(Seq[Int],T)=(Seq.empty[Int],this.zero)
}
由于超类和混合类具有相同的方法名(显然),我们无法引用正确的方法。我唯一的选择是使用构图吗
如何堆叠此类操作?第一种方法有一个基本的理论问题: 假设我们被允许写这些特征。然后考虑以下内容:
val acc = new XAccumulator with TraceYAccumulator
val xacc = acc: XAccumulator
由于xacc
是一个xaccumpulator
,我们知道x.R=:=Int
。哎呀
第二种方法有一个实现问题:不能从同一特性的不同实例继承
illegal inheritance; anonymous class $anon inherits different type instances of trait Accumulator: Accumulator[Int] and Accumulator[(Seq[Int], Int)]
因此,组合(或者某些类型类黑客)似乎是唯一的选择。不确定这是否会像您希望的那样起作用。stackable trait模式涉及通过调用super将函数彼此链接起来。如果链中的每个特征都可能具有不同的泛型类型,那么我看不出调用如何正确地进行链。如果它们都是用相同的类型参数化的,这可能会起作用。@cmbaxter调用可以正确地链接,因为堆叠特性将堆叠特性的返回类型作为其返回类型。当然,整个堆栈的最终返回类型将取决于堆栈特征的顺序。我看不出我的方法的理论问题在哪里。