【问题标题】:Scala trait extending abstract class, how do I know whether an abstract method has been implemented or notScala trait扩展抽象类,我怎么知道抽象方法是否已经实现
【发布时间】:2018-02-01 10:13:13
【问题描述】:

我是 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 方法返回空列表,但我只是好奇是否有办法检查父类中的方法是否已实现。

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

【问题讨论】:

  • 它看起来像装饰器模式,但我不确定你的目标是什么

标签: scala overriding abstract traits


【解决方案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
  }
}

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

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)
  }
}

【讨论】:

  • 谢谢,所以这意味着我仍然需要尽早在整个路径中实现。有没有办法:如果实现了 super ,调用它;如果 super 没有实现,做第一个实现?
  • 你的意思是在编译时还是在运行时?如果您在运行时需要,那么我不知道,它应该涉及反射 API 和类似的魔法,我尽量避免这样做。如果你想在编译时知道(例如,你正在使用一个你没有源代码的库),那么编译器会告诉你它是否没有实现(在我的例子中是WithoutImpl)。还是我误解了你的问题?
  • 谢谢,我问的是运行时间。但是你的解决方案有效,我保证之前有实现。
  • 我是 scala 的新手,我试图理解为什么在WithoutImpl 中,当特征 AA 中的 foo() 确实定义了实现时,该函数被认为没有实现。我假设如果添加了“抽象”,它会起作用吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-16
  • 2012-05-03
  • 2013-05-30
相关资源
最近更新 更多