在scala中一般性地实例化特征

时间:2012-06-01 14:01:30

标签: scala generics traits

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

假设:

//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等)返回两种类型的组合,以便我可以将东西链接在一起。基本上我想做:     特质A {       def doThing = {         新的A与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. 我无法通过通用参数

  4. 实例化我的匿名类
  5. 我无法定义特征中函数的返回类型,因为我 不知道这种类型,直到它与某种东西混合在一起。

  6. 对于scala来说,我有点像菜鸟,我觉得我会以完全错误的方式解决这个问题,也许我应该使用implicits和CanBuildFrom模式。任何帮助将不胜感激。

    干杯

1 个答案:

答案 0 :(得分: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继承一些具有不同参数的特征,这是多次被着名类型擦除所禁止的