0

我正在尝试将 Scala 的蛋糕模式与具有多个组(层)的通用拦截器一起使用。当一层的末尾需要另一层时,我尝试使用 self 类型来表达。但它因非法继承而失败。该任务的一般背景是我有一个文档模型,我正在尝试在其上进行验证链。玩具示例如下,每一层仅由一个特征表示。

trait Element
trait Leaf extends Element
trait Composed extends Element

trait Validator [A] {def validate (element : A) : String}

//second layer
trait LeafValidator extends Validator[Leaf]{
  override def validate (element : Leaf) : String = "leaf"}

//first layer
trait ElementValidator extends Validator[Element]{
  self : Validator[Leaf] =>

  override def validate (element : Element) : String = element match {
    case leaf : Leaf => super.validate(leaf)
    case _ => "other"
  }
}

case class Concrete extends LeafValidator with ElementValidator

错误在实例化线上

非法继承;self-type apltauer.david.util.Concrete 不符合 apltauer.david.util.ElementValidator 的 selftype apltauer.david.util.ElementValidator 和 apltauer.david.util.Validator[apltauer.david.util.Leaf] Main.scala / Dependency/src/apltauer/david/util 第 56 行 Scala 问题

逆变抑制了错误,但并没有解决问题,因为此时 self 类型是无用的。

4

1 回答 1

0

我有同样的问题。使用两种功能变体打破了(否则,很好和有用的)蛋糕模式。

所以我开发了一个增强功能,就我的问题而言,它允许我保持蛋糕图案完整,我称之为Feature Pattern。在你的情况下:

trait element_validator extends validator[Element] {
   final override val element_validator = this
}
trait feature_element_validator { val element_validator : element_validator }

/* Analogous for “Leaf” */

trait validator[element_type] {
   final override val validator = this
   /* Feature code here: */
   def validate(element: element_type) = /* … */
}
trait feature_validator[element_type] { val validator : validator[element_type] }

所以现在可以说:

object component
   extends element_validator
   with leaf_validator
   with other_cake_feature_1
   with other_cake_feature_2
   with other_cake_feature_3
   /* etc. */

内部组件一将区分两种验证器:

element_validator.validate(…)
leaf_validator.validate(…)

如果只有一个需要,则导入(这与使用自类型注释来获取名称的可用性具有相同的效果):

import element_validator._
validate(…)

我知道,这是相当一些样板。但是,除了将蛋糕与组合物结合起来(只要需要组合物时),我没有看到任何其他解决方案。

于 2015-07-03T13:54:50.010 回答