Scala特性扩展抽象类,我如何知道是否已经实现了抽象方法

时间:2018-02-01 10:13:13

标签: scala override abstract traits

我是scala的新手,我有以下问题

abstract class A {
    def foo(): List[String]
}

trait AA extends A {
    override def foo(): List[String] = {
        // Something like 
        // If super.foo is implemented, "AA" +: super.foo
        // If super.foo is not implemented, List("AA")
    }
}

class B extends A with AA {
    override def foo(): List[String] = {
        // I think the trait will have the implementation, so I should only need to do:
        super.foo
    }
}

基本上我希望每个特性在foo的结果中添加一个部分,这样我就可以通过混合多个这样的特征来获得最终结果。我想我可以在A类中使foo方法返回空List,但我只是好奇是否有办法检查父方法是否已经实现。

另外,如果有反模式,请告诉我。

1 个答案:

答案 0 :(得分:1)

我想你想要stackable trait pattern

所以你有一个抽象类A,它声明了一些方法foo(),你有一个"装饰器"那个方法的人说的是"我延伸A并且我想追加' AA'无论foo()返回什么"。

abstract class A {
  def foo(): List[String]
}

trait AA extends A {
  abstract override def foo(): List[String] = "AA" :: super.foo()
}

注意abstract override,这是关键。它允许我们将一些行为附加到抽象类。

现在让我们说我们这样做:

class WithoutImpl extends A with AA {
  override def foo(): List[String] = {
    super.foo() // fails; needs "abstract override" or implementation
  }
}

这失败了,因为每个人都在装修,但实际上没有人在实施。

让我们添加一个实现特征:

trait AAA extends A {
  override def foo(): List[String] = List("AAA")
}

现在我们可以这样做:

class WithImpl extends AA with AAA {
  def myFoo(): List[String] = {
    super.foo() // error! wrong order of initialization
  }
}

由于mixins的顺序,这仍然会失败。我们必须首先提供一个实现,然后我们提供装饰者,然后他们将继续添加行为。

class WithImpl extends AAA with AA  {
  def myFoo(): List[String] = {
    super.foo() // works!
  }
}

println((new WithImpl().myFoo())) // List("AA", "AAA")

您可以根据需要添加任意数量的装饰器,只需注意订单即可。例如。如果我们BBCC类似于AA,我们可以这样做:

class WithImpl extends AAA with AA with BB with CC  {
  def myFoo(): List[String] = {
    super.foo() // List(CC, BB, AA, AAA)
  }
}