Scala Traits - 如何多次扩展一个特征?
Scala Traits - How to extend a trait multiple times?
我是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
延长了一倍)
基数类在线性化中只能出现一次:
https://www.scala-lang.org/files/archive/spec/2.12/05-classes-and-objects.html#class-linearization
Let C
be a class with template C1 with ... with Cn { stats }
. The linearization of C
, L(C)
is defined as follows:
L(C) = C, L(Cn) +⃗ … +⃗ L(C1)
Here +⃗
denotes concatenation where elements of the right operand replace
identical elements of the left operand:
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]
我是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
延长了一倍)
基数类在线性化中只能出现一次:
https://www.scala-lang.org/files/archive/spec/2.12/05-classes-and-objects.html#class-linearization
Let
C
be a class with templateC1 with ... with Cn { stats }
. The linearization ofC
,L(C)
is defined as follows:
L(C) = C, L(Cn) +⃗ … +⃗ L(C1)
Here
+⃗
denotes concatenation where elements of the right operand replace identical elements of the left operand: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]