學(xué)會了怎么創(chuàng)建類, 我們繼續(xù)用它來構(gòu)建我們的中心內(nèi)容:
class Hammer {
method hammer($stuff) {
say "You hammer on $stuff. BAM BAM BAM!";
}
}
class Gavel {
method hammer($stuff) {
say "You hammer on $stuff. BAM BAM BAM!";
}
}
class Mallet {
method hammer($stuff) {
say "You hammer on $stuff. BAM BAM BAM!";
}
}
但是注意到了嗎? 這三個方法包含了同樣的方法, 在類中重復(fù)了。我們必須那樣做如果我們想讓每個 Hammar、Gavel 和 Mallet 有能力擊打的話。(并且那是合理的)割笙。 但是遺憾的是我們不得不把那個方法一式三份。
為什么遺憾眯亦? 因?yàn)橐环矫嬖谡鎸?shí)世界中, 方法并不是很彼此相似, 有一天你決定在 hammer 方法中更改某些東西, 并沒有意識到這個方法在三個不同的地方... 這導(dǎo)致了一堆痛苦和難受伤溉。
所以我們的新玩具, 類, 展現(xiàn)出了一個問題。我們想在每個類中重用 hammer 方法妻率。一個新的概念, role 來拯救我們來了:
role Hammering {
method hammer($stuff) {
say "You hammer on $stuff. BAM BAM BAM!";
}
}
雖然類經(jīng)常以一個合適的名詞命名, 但是 roles 經(jīng)常以一個分詞命名, 例如 Hammering乱顾。這不是一個必須遵守的規(guī)則, 但是它是一個好的經(jīng)驗(yàn)法則。現(xiàn)在類的定義變的簡單了:
class Hammer does Hammering { }
class Gavel does Hammering { }
class Mallet does Hammering { }
是的, 我們喜歡那樣宫静。
這發(fā)生了什么走净? 我們在類上使用 does 是干什么用的? role 定義中的所有方法都被拷貝到類定義中孤里。因?yàn)樗且粋€拷貝操作, 所以我們可以使用盡可能多的類伏伯。
所以, 我們做的是: 當(dāng)我們想重用方法的時候把方法放進(jìn) roles 里面。
但是好處不止這一點(diǎn)兒捌袜。至少有兩個好處:
my $hammer = Hammer.new; # create a new hammer object
say $hammer ~~ Hammer; # "Bool::True" -- yes, this we know
say $hammer ~~ Hammering; # "Bool::True" -- ooh!
所以 $hammer
知道它遵守了(does)Hammering, 我們現(xiàn)在不僅知道了對象屬于哪個類, 還知道了對象并入了什么 role说搅。這很有用如果我們不確定我們處理的是什么類型的對象:
if $unkown_object ~~ Hammering {
$unknown_object.hammer("砸在釘子上"); # will always work
}
一個類能一次接收幾個 roles 嗎? 是的, 它可以:
role Flying {
method fly {
say "Whooosh!";
}
}
class FlyingHammer does Hammering does Flying { }
讓一個類像那樣遵守幾個 roles 引入了一個有意思的可能: 沖突, 當(dāng)來自兩個不同 roles 的兩個同名方法嘗試占領(lǐng)同一個類時虏等。這時會發(fā)生什么弄唧? 好吧, 至少有 3 種可能:
- 第一個 role 贏了适肠。 它的方法住進(jìn)了類中
- 最后一個 role 贏了。 它覆蓋了之前的方法
- 編譯失敗候引。沖突必須被解決迂猴。
這種情況下選項(xiàng) 3 應(yīng)該是正確答案。原因和之前相同: 因?yàn)轭惡凸こ淘絹碓烬嫶? 程序員可能意識不到兩個 role 之間在哪兒發(fā)生沖突背伴。所以我們標(biāo)記了它。
role Sleeping {
method lie {
say "水平躺下";
}
}
role Lying {
method lie {
say "說謊...";
}
}
class SleepingLiar does Sleeping does Lying { } # 沖突!
下一個問題, 那么: 當(dāng)在類中有 role 沖突時, 我們怎么修復(fù)它峰髓? 簡單: 在類中自己定義一個同名的方法:
class SleepingLiar does Sleeping does Lying {
method lie {
say "Lying in my sleep....";
}
}
如果你想從一個貼別的 role 中調(diào)用一個方法, 語法是這樣的:
class SleepingLiar does Sleeping does Lying {
method lie {
self.Sleeping::lie;
}
}
這就是 roles傻寂。它們把可重用的行為混合進(jìn)類中。