Perl 6 - roles 沖突

學會了怎么創(chuàng)建類, 我們繼續(xù)用它來構建我們的中心內(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!";
    }
}

但是注意到了嗎? 這三個方法包含了同樣的方法, 在類中重復了。我們必須那樣做如果我們想讓每個 HammarGavelMallet 有能力擊打的話。(并且那是合理的)。 但是遺憾的是我們不得不把那個方法一式三份。

為什么遺憾? 因為一方面在真實世界中, 方法并不是很彼此相似, 有一天你決定在 hammer 方法中更改某些東西, 并沒有意識到這個方法在三個不同的地方... 這導致了一堆痛苦和難受。

所以我們的新玩具, 類, 展現(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)驗法則。現(xiàn)在類的定義變的簡單了:


class Hammer does Hammering { }
class Gavel  does Hammering { }
class Mallet does Hammering { }

是的, 我們喜歡那樣。

這發(fā)生了什么? 我們在類上使用 does 是干什么用的? role 定義中的所有方法都被拷貝到類定義中。因為它是一個拷貝操作, 所以我們可以使用盡可能多的類。

所以, 我們做的是: 當我們想重用方法的時候把方法放進 roles 里面。

但是好處不止這一點兒。至少有兩個好處:


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 引入了一個有意思的可能: 沖突, 當來自兩個不同 roles 的兩個同名方法嘗試占領同一個類時。這時會發(fā)生什么? 好吧, 至少有 3 種可能:

    1. 第一個 role 贏了。 它的方法住進了類中
    1. 最后一個 role 贏了。 它覆蓋了之前的方法
    1. 編譯失敗。沖突必須被解決。

這種情況下選項 3 應該是正確答案。原因和之前相同: 因為類和工程越來越龐大, 程序員可能意識不到兩個 role 之間在哪兒發(fā)生沖突。所以我們標記了它。


role Sleeping {
    method lie {
        say "水平躺下";
    }
}

role Lying {
    method lie {
        say "說謊...";
    }
}

class SleepingLiar does Sleeping does Lying { }    # 沖突!

下一個問題, 那么: 當在類中有 role 沖突時, 我們怎么修復它? 簡單: 在類中自己定義一個同名的方法:


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。它們把可重用的行為混合進類中。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容

  • Object Orientation in Perl 6 Perl 6 有很多預先定義好的類型,這些類型可以歸為 ...
    焉知非魚閱讀 481評論 0 1
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內(nèi)部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,767評論 18 399
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,462評論 25 708
  • 2009 有用的和有意思的循環(huán) 讓我們來看一個基本的例子. 這是一個最簡單清晰的語法的例子.在這并沒有使用括號來包...
    焉知非魚閱讀 595評論 0 0
  • 22年12月更新:個人網(wǎng)站關停,如果仍舊對舊教程有興趣參考 Github 的markdown內(nèi)容[https://...
    tangyefei閱讀 35,235評論 22 257