我正在尝试将Scala的蛋糕模式与具有多个组(层)的通用拦截器一起使用。当一个层的结尾需要另一个层时,我尝试用自我类型来表达。但它失败了非法继承。这个任务的一般背景是我有一个文档模型,我正在尝试进行验证链。玩具示例如下,每个图层仅由一个特征表示。
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 /依赖/ src / apltauer / david / util行56 Scala问题
逆变法抑制了错误,但没有解决问题,因为自我类型无用。
答案 0 :(得分:0)
我遇到了同样的问题。使用两种特征变形打破了(否则,漂亮和有用)蛋糕模式。
所以我开发了一个增强功能,就我的问题而言,它允许我保持蛋糕图案完好无损,我称之为特征模式。在你的情况下:
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(…)
我知道,这是一些样板。然而,我没有看到任何其他解决方案,而不是将蛋糕与成分结合起来(无论何时需要组合物)。