`

O'REILLY版《Programming Scala》学习笔记——Trait

阅读更多
package ui
import observer._
//with关键字类似JAVA的implements关键字,但是和JAVA不同的是在声明多个traits时每个traits都要有属于自己的with
class ObservableButton(name: String) extends Button(name) with Subject {
  override def click() = {//因为click()是覆盖父类Button的方法,这里不许使用override 
    super.click()
    notifyObservers
  }
}

//If you don’t use extends for the first trait, e.g., you write the following:
// ERROR:
class ObservableButton(name: String) with Button(name) with Subject {...}

引用

You’ll get an error like this:
... error: ';' expected but 'with' found.
class ObservableButton(name: String) with Button(name) with Subject {...}

注意:如果一个Class使用多个traits,但它没有继承其他Class时。第一个traits不能使用with关键字而要改成extends。
//trait中抽象方法或者类不需要加abstract
trait Clickable {
def click()
}

package ui2
import observer._

trait ObservableClicks extends Clickable with Subject {
//这里的方法为什么使用abstract?因为这里的方法体中使用了 super.click()但是它的父trait又没有实现click()方法。使用abstract告诉编译器这个方法没有完全实现。
  abstract override def click() = {
    super.click()
    notifyObservers
  }
}

package ui2
import org.specs._
import observer._
import ui.ButtonCountObserver

object ButtonClickableObserverSpec extends Specification {
  "A Button Observer" should {
    "observe button clicks" in {
      val observableButton = new Button("Okay") with ObservableClicks
      val buttonClickCountObserver = new ButtonCountObserver
      observableButton.addObserver(buttonClickCountObserver)

      for (i <- 1 to 3) observableButton.click()
      buttonClickCountObserver.count mustEqual 3
    }
  }
}
//这里例子展示了在创建Button实例的时候混入了ObservableClicks。本来Button的实例是要求实现一个click()方法的,但是这个工作已经由ObservableClicks完成了。

package ui2
import org.specs._
import observer._
import ui.ButtonCountObserver

object ButtonClickableObserverVetoableSpec extends Specification {
  "A Button Observer with Vetoable Clicks" should {
    "observe only the first button click" in {
     //ObservableClicks和VetoableClicks都实现了click()方法
     //click()方法的覆盖顺序:右边trait的click方法覆盖左边trait的click方法
     //即VetoableClicks.click()中调用super.click()将执行ObservableClicks.click()
      val observableButton = 
          new Button("Okay") with ObservableClicks with VetoableClicks
      val buttonClickCountObserver = new ButtonCountObserver
      observableButton.addObserver(buttonClickCountObserver)

      for (i <- 1 to 3) observableButton.click()
      buttonClickCountObserver.count mustEqual 1
    }
  }
}

trait不支持辅助构造函数,也不支持带参数列表的主构造函数
trait能继承自Class和其他的trait
trait T1 {
  println( "  in T1: x = " + x )
  val x=1
  println( "  in T1: x = " + x )
}
trait T2 {
  println( "  in T2: y = " + y )
  val y="T2"
  println( "  in T2: y = " + y )
}

class Base12 {
  println( "  in Base12: b = " + b )
  val b="Base12"
  println( "  in Base12: b = " + b )
}
class C12 extends Base12 with T1 with T2 {
  println( "  in C12: c = " + c )
  val c="C12"
  println( "  in C12: c = " + c )
}
println( "Creating C12:" )
new C12
println( "After Creating C12" )

上面的代码的输出如下:
引用

Creating C12:
in Base12: b = null
in Base12: b = Base12
in T1: x = 0
in T1: x = 1
in T2: y = null
in T2: y = T2
in C12: c = null
in C12: c = C12
After Creating C12

这个例子中构造函数的执行顺序从Base12 到T1到T2,最后执行的是C12的构造函数。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics