Scala特性-如何多次扩展特征?

时间:2018-07-14 08:23:34

标签: scala decorator traits

我对Scala不友好,请参见以下代码。

abstract class Pizza() {
  def toppings: List[String]
  def price: BigDecimal
}
trait Large extends Pizza {
  abstract override def price: BigDecimal = super.price * 2
}
trait Cheese extends Pizza {
  abstract override def toppings: List[String] = "Cheese" :: super.toppings
  abstract override def price: BigDecimal = super.price + 0.5
}
trait Salami extends Pizza {
  abstract override def toppings: List[String] = "Salami" :: super.toppings
  abstract override def price: BigDecimal = super.price + 1.0
}
class BasePizza extends Pizza {
  def toppings = List("Tomato Sauce")
  def price = 5.0
}
class MargheritaPizza extends BasePizza with Cheese
class LargeMargheritaPizza extends MargheritaPizza with Large
class SalamiPizza extends MargheritaPizza with Salami
class DoubleCheeseSalamiPizza extends MargheritaPizza with Salami with Cheese


println(reflect.runtime.universe.typeOf[DoubleCheeseSalamiPizza].baseClasses)
// List(class DoubleCheeseSalamiPizza, trait Salami, class MargheritaPizza, trait Cheese, class BasePizza, class Pizza, class Object, class Any) res0: Unit = ()

如何多次添加装饰?例如披萨和双层奶酪? (如您所见,线性化顺序trait Cheese扩展了一次)

1 个答案:

答案 0 :(得分:4)

基类只能线性化一次:

https://www.scala-lang.org/files/archive/spec/2.12/05-classes-and-objects.html#class-linearization

  

C为带有模板C1 with ... with Cn { stats }的类。 CL(C)的线性化定义如下:

     

L(C) = C, L(Cn) +⃗ … +⃗ L(C1)

     

此处+⃗表示串联,其中右操作数的元素替换   左操作数的相同元素:

a, A +⃗ B = a, (A +⃗ B)  if a ∉ B
         = A +⃗ B       if a ∈ B

https://github.com/scala/scala/blob/2.13.x/src/reflect/scala/reflect/api/Types.scala#L176-L180

/** The list of all base classes of this type (including its own typeSymbol)
 *  in linearization order, starting with the class itself and ending
 *  in class Any.
 */ def baseClasses: List[Symbol]