1.什么是Trait ?

Traits are a fundamental unit of code reuse in Scala. A trait encapsulates

method and field definitions, which can then be reused by mixing them into
classes. Unlike class inheritance, in which each class must inherit from just
one superclass, a class can mix in any number of traits.

Traits是Scala中代码复用的基本单元

类似Java中的接口,但是可以定义method和field

2. 第一个Trait, 具有哲学家特征的青蛙,哈哈

package chapter12trait Philosophical {  def philosophise() = println("I consume memory, therefor I am !")}class Frog extends Philosophical {  override def toString = "green"}object TestMain {  def main(args: Array[String]) {    val frog = new Frog    frog.philosophise()    //I consume memory, therefor I am !  }}

This trait is named Philosophical. It does not declare a superclass, so

like a class, it has the default superclass of AnyRef. It defines one method,
named philosophize, which is concrete.

默认继承 AnyRef

Once a trait is defined, it can be mixed in to a class using either the

extends or with keywords

用关键字: extends 或 with 将Trait混入类

You can use the extends keyword to mix in a trait; in that case you

implicitly inherit the trait’s superclass
当用extends 关键字时,该类隐式地继承了trait的父类

A trait also defines a type.

定义一个trait的同时也定义了一个新的类型

    val philo: Philosophical = new Frog    philo.philosophise()

3.显式声明父类,重载trait的方法

package chapter12trait Philosophical {  def philosophise() = println("I consume memory, therefor I am !")}class Cat class Frog extends Cat with Philosophical {  override def toString = "green"  override def philosophise() = println("It ain't easy to being " + toString)}

4.At this point you might philosophize that traits are like Java interfaces

with concrete methods, but they can actually do much more. Traits can, for
example, declare fields and maintain state. In fact, you can do anything in
a trait definition that you can do in a class definition, and the syntax looks
exactly the same, with only two exceptions.

Trait可以做class可以做的所有事情,只有两点例外

第一,trait 不能包含类参数,也就是说不能有构造函数

trait Philosophical(x: Int, y: Int) {  def philosophise() = println("I consume memory, therefor I am !")}  // 编译无法通过

第二,使用super调父类方法的时候,class中是静态绑定的,trait中是动态绑定的

The other difference between classes and traits is that whereas in classes,

super calls are statically bound, in traits, they are dynamically bound. If
you write “super.toString” in a class, you know exactly which method
implementation will be invoked. When you write the same thing in a trait,
however, the method implementation to invoke for the super call is undefined when you define the trait. Rather, the implementation to invoke will
be determined anew each time the trait is mixed into a concrete class. This
curious behavior of super is key to allowing traits to work as stackable modifications

关于可堆叠的更改(stackable modification)后面会详细说明


5.再看一个例子

package chapter12class Point(val x: Int, val y: Int)trait Rectangular {  def topLeft: Point  def bottomRight: Point    def left = topLeft.x   def right = bottomRight.x   def width = right - left}abstract class Component extends Rectangularclass Rectangle (val topLeft: Point, val bottomRight: Point) extends Rectangular

这样所有的组件和矩形都有了Rectangular提供的几何方法

6. Ordered Trait

package chapter12trait Ordered[T] {  def compare(that: T): Int  def > (that: T) = compare(that) > 0  def < (that: T) = compare(that) < 0  def >= (that: T) = (this > that) || (this == that)  def <= (that: T) = (this < that) || (this == that)}class Rational(val n: Int, val d: Int) extends Ordered[Rational] {   def compare(that: Rational) = this.n * that.d  - this.d * that.n   def equals(that: Rational) = (this.n * that.d - this.d * that.n) == 0}object TestMain {  def main(args: Array[String]) {    val r1 = new Rational(3, 4)    var r2 = new Rational(1, 2)    println(r1 == r2)    println(r1 > r2)    println(r1 <= r2)  }}

客户代码只需实现compare和equals, > < >= <=由trait实现

trait中的this在这里就是动态绑定的,同理super也是