一个更复杂的例子
下面的例子将展示trait的更多特性
trait Trader {
int availableMoney = 0
private int tradesDone = 0
def buy(Item item) {
if (item.price <= availableMoney) {
availableMoney -= item.price
tradesDone += 1
println "${getName()} bought ${item.name}"
}
}
def sell(Item item) {
..
}
abstract String getName()
}
就像Groovy类,trait也支持属性。本例中,availableMoney
属性将变成私有的,同时相应的setter和getter方法会被自动生成。在实现中可以访问这些方法。但无法在Trader以外访问tradesDone
私有变量。我们还定义了一抽象方法getName(),实现类必须实现它。
现在就创建一个实现Trader的类:
class Merchant implements Trader {
String name
String getName() {
return this.name
}
}
现在Merchant就可以购买东西了:
def bike = new Item(name: 'big red bike', price: 750)
def paul = new Merchant(name: 'paul')
paul.availableMoney = 2000
paul.buy(bike) // prints "paul bought big red bike"
println paul.availableMoney // 1250
trait的扩展、覆盖、解决冲突
trait使用extends关键字实现继承:
trait Dealer {
def getProfit() { ... }
def deal() { ... }
}
trait CarDealer extends Dealer {
def deal() { ... }
}
在这里,CarDealer继承了Dealer,同时覆盖了Dealer的deal()方法。
trait的方法也可以被实现类覆盖:
class OnlineCarDealer implements CarDealer {
def deal() { ... }
}
如是一个类同时实现了多个trait,就很有可能产生冲突。因为超过一个trait使用了相同的签名:
trait Car {
def drive() { ... }
}
trait Bike {
def drive() { ... }
}
class DrivingThing implements Car, Bike { ... }
在这种情况下,只有后一个trait定义生效。(本例中Bike生效)。
总结
trait是一个非常有用的概念,很开心在Groovy中看到它。Groovy混合trait是在编译期,因此,Java可以调用trait(Other than Groovy mixins traits work at compile time and can therefore be accessed from Java code)。进一步学习,我推荐Groovy 2.3的Trait 文档。