http://www.javacodegeeks.com/2014/04/groovy-2-3-introduces-traits.htmlhtml
前幾天,Groovy 2.3的第二個beta版本發佈。Groovy 2.3最重要的新特性之一是trait語法。trait是一組可重用的方法和字段,能夠將它們混入到一個或多個類中。一個類能夠同時擁有多個trait而不須要使用多重繼承(從而避免鑽石問題)。java
在Groovy 2.3中,這樣定義一個基本的trait:app
trait SwimmingAbility { def swim() { println "swimming.." } }
trait的定義與類的定義很是類似。SwimmingAbility trait只定義了一個swim()方法。接下來就可使用implements關鍵字來向類中加入這個trait:學習
class Goldfish implements SwimmingAbility { .. }
如今,咱們就能夠調用Goldfish對象的swim()方法了。this
def goldfish = new Goldfish() goldfish.swim()
到這裏,咱們已經實現了與繼承一樣的功能。不一樣的是,咱們能夠添加多個trait到同一個類中。下面,咱們定義其它的trait:code
trait FlyingAbility { def fly() { println "flying.." } }
再建立一個新的類,同時使用這些trait:htm
class Duck implements SwimmingAbility, FlyingAbility { .. }
如今鴨子能夠遊動和飛了:對象
def duck = new Duck() duck.swim() duck.fly()
trait中的this關鍵字表明瞭trait的實現的實例,因此,你能夠這樣寫:繼承
trait FlyingAbility { def fly() { println "${this.class.name} is flying.." } }
若是調用duck.fly()
,將會打印:ip
Duck is flying..
下面的例子將展現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使用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 文檔。