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

本文深入探讨Scala中特质(trait)的使用方法及其与类的构造函数之间的交互过程。通过具体的代码示例,详细解释了如何在Scala中定义和使用特质,并说明了特质与类构造函数的执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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 {...}

[quote]
You’ll get an error like this:
... error: ';' expected but 'with' found.
class ObservableButton(name: String) with Button(name) with Subject {...}
[/quote]
注意:如果一个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" )

上面的代码的输出如下:
[quote]
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
[/quote]
这个例子中构造函数的执行顺序从Base12 到T1到T2,最后执行的是C12的构造函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值