简体   繁体   English

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

[英]Scala trait extending abstract class, how do I know whether an abstract method has been implemented or not

I am new to scala, and I have the following question 我是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
    }
}

Basically I would like each trait to add one part to the result of foo, so that I can have the final result by mixing multiple such traits. 基本上,我希望每个特征都可以在foo的结果中添加一部分,以便可以通过混合多个这样的特征来获得最终结果。 I think I can make the foo method in class A to return empty List, but I am just curious whether there is a way to check whether the method in parent has been implemented or not. 我想我可以使A类中的foo方法返回空的List,但是我很好奇是否有一种方法可以检查父类中的方法是否已实现。

Also, please let me know if there is an anti-pattern. 另外,请告诉我是否有反模式。

I think you want the stackable trait pattern . 我认为您需要可堆叠的特征模式

So you have an abstract class A which declares some method foo() , and you have a "decorator" of that method who says something like "I extend A and I would like to append 'AA' to whatever foo() returns". 因此,您有一个声明了某些方法foo()的抽象类A ,并且您具有该方法的“修饰符”,其声明为“我扩展了A并且我想将'AA'附加到foo()返回的任何内容上”。

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

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

Note the abstract override , this is the key. 注意abstract override ,这是关键。 It allows us to append some behaviour to an abstract class. 它允许我们将某些行为附加到抽象类。

Now let's say we do something like this: 现在让我们说这样的事情:

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

This fails because everyone is decorating, but noone is actually implementing. 这失败了,因为每个人都在装饰,但实际上没有人在实现。

Let's add an implementation trait: 让我们添加一个实现特征:

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

Now we might do: 现在我们可以这样做:

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

This will still fail due to the order of mixins. 由于混合命令的顺序,这仍然会失败。 We must first provide an implementation, and then we provide the decorator(s), who will then keep adding behaviours. 我们必须首先提供一个实现,然后提供装饰器,然后装饰器将继续添加行为。

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

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

You can add as many decorators as you wish, just pay attention to the order. 您可以根据需要添加任意数量的装饰器,只需注意顺序即可。 Eg if we had BB and CC similarly to AA , we could do: 例如,如果我们的BBCCAA相似,则可以执行以下操作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM