3

我正在尝试制作一个允许用户将多个处理器链接在一起的系统。我遇到的困难是每个处理器实际上都有它关心的两位信息,我希望以类型安全的方式处理这些信息。我把它归结为这个问题:

鉴于:

//First family of stuff
trait A {
  def doA {}
}

trait B {
  def doB {}
} 

//Second family of stuff
trait X {
  def doX {}
}

trait Y {
  def doY {}
} 

我可以将这两个家族的元素组合成 4 种口味:

var f = new A with X {}
f.doA
d.doX

var g = new A with Y {}
//...

伟大的。问题是我希望每个函数(doA 等)返回两种类型的组合,以便我可以将东西链接在一起。本质上我想做: trait A { def doThing = { new A with ThingThatImmixedInWithLikeXOrY {} } }

每个处理器都需要返回一个匿名类,该类包括 1) 处理器已知的类型 2) 与之混合的类型。

我的第一个尝试是使用泛型,如下所示:

trait A {
  this : {def makeWithT[TOther]} =>
  def doA = makeWithT[B]
}

trait B {
  this : {def makeWithT[TOther]} =>
  def doB = makeWithT[A]
}

trait X {
  this : {def makeWithS[TOther]} =>
  def doX = makeWithT[Y]
}

trait Y {
  this : {def makeWithS[TOther]} =>
  def doY = makeWithT[Y]
}

class Foo[T, S] extends S with T {
  def makeWithT[OtherT] = new T with OtherT
  def makeWithS[OtherT] = new S with OtherT
}

var f = new Foo[A, X]
f.doA.doB
f.doX.doA
f.doX.doY
...

显然,我遇到了一系列问题:

  1. 我不能创建一个从类型参数扩展的泛型类

  2. 我无法通过泛型参数实例化我的匿名类

  3. 我无法在 trait 中定义函数的返回类型,因为在它与某些东西混合之前我不知道类型。

当谈到 scala 时,我有点菜鸟,我觉得我正在以完全错误的方式处理这个问题,也许我应该使用隐式和 CanBuildFrom 模式。任何帮助将不胜感激。

干杯

4

1 回答 1

1

可堆叠处理器最著名的解决方案是可堆叠特征

http://www.artima.com/scalazine/articles/stackable_trait_pattern.html

trait StackableRoot {
  def StackablePass (x:Int) : x
}
trait StackableDouble extends StackableRoot {
  def internalPass (x:Int) = 2*x
  abstract override def StackablePass(x:Int) = super.StackablePass(internalPass(x))
}
trait StackableIncrement extends StackableRoot {
  def internalPass (x:Int) = x+1
  abstract override def StackablePass(x:Int) = super.StackablePass(internalPass(x))
}

有一些样板

  abstract override def StackablePass(x:Int) = super.StackablePass(internalPass(x))

这无法通过打包到参数化特征中来避免,因为它需要 scala 多次继承一些具有不同参数的特征,而著名的类型擦除则禁止这些特征

于 2012-06-01T17:43:11.983 回答