Perl 6 中的 bless

bless 方法


method bless(*%attrinit) returns Mu:D

相比 new方法來說更低層級別的對象構(gòu)造方法驴党。

創(chuàng)建一個和調(diào)用者同類型的新對象, 使用具名參數(shù)來初始化屬性, 并返回創(chuàng)建后的對象寻拂。

在自定義構(gòu)造函數(shù)時可以使用該方法:

class Point {
    has $.x;
    has $.y;

    # multi 是可選的
    multi method new($x, $y) {
        self.bless(:$x, :$y);
    }
}

# 重寫構(gòu)造函數(shù)后, 不需要傳具名參數(shù)了
my $p = Point.new(-1, 1);
say $p.x; # -1

雖然你可以自定義構(gòu)造函數(shù), 記得它會讓子類繼承變得更困難精置。

use v6;

# bless 的原理
class Dog {
    has $.name;
    my $.counter; # 類方法
    # 重寫 new 方法, 使用位置參數(shù)創(chuàng)建實例
    method new ($newName) {
        $.counter++;
        self.bless(name => $newName);
    }
}

my $dog = Dog.new("yayaya");
say $dog.name;   # yayaya
say Dog.counter; # 1

讓我們創(chuàng)建一個對象


在 Perl 6 中創(chuàng)建一個對象相當(dāng)容易餐屎。 作為類的作者你真的不必關(guān)心(至少在最簡單的情況下), 你從 Mu 類繼承了一個默認(rèn)的構(gòu)造函數(shù)艳吠。作為類的使用者, 你僅僅寫出 MyClass.new(attrib1 => $value1) 就能創(chuàng)建一個 MyClass類的對象, 同時初始化了一個公開的屬性 attrib1主卫。

運行初始化代碼


如果你想在對象創(chuàng)建中運行某些初始化代碼, 那么你一點兒也沒有必要動用 new方法。使用 BUILD 子方法:

class C {
    submethod BUILD {
        say "創(chuàng)建一個 C 的實例";
    }
}

C.new();  # 創(chuàng)建一個 C 的實例

BUILD submethod 由構(gòu)造函數(shù)自動調(diào)用, 并且可以處理任何必要的初始化虾宇。BUILD submethod 也能接收用戶傳遞給 new() 方法的具名參數(shù)搓彻。

(以防你疑惑, submethod不能被子類繼承的方法。)

因為 BUILD 運行在尚未完全構(gòu)建好的對象上, 屬性只有在被聲明為具名參數(shù)的時候才可以被訪問:

submethod BUILD(:$!attr1, :$!attr2) {
    # 這兒可以使用 $!attr1 和 $!attr2
}

該語法也自動的使用和 new方法同名的具名參數(shù)的值初始化屬性 嘱朽。

use v6;

class Cat {
    has $.fullname;
    has $.nickname;

    submethod BUILD(:$!fullname, :$!nickname) {
        say "造了一只貓, 它的全名是 $!fullname, 它的昵稱是 $!nickname";
    }
}

# 造了一只貓, 它的全名是 Camelia, 它的昵稱是 Rakudo Star
Cat.new(fullname => 'Camelia', nickname => 'Rakudo Star');

所以下面的兩個類聲明, 表現(xiàn)一樣:

class D {
    has $.x;
}
# and
class D {
    has $!x;                   # 私有屬性
    submethod BUILD(:$!x) {}   # 允許 D.new( x => $x )
    method x() {$!x}           # accessor
}

這也解釋了 has $.x 等價于 has $!x 加上 accessor 的原理旭贬。

自定義構(gòu)造函數(shù)


假如你對具名參數(shù)不感冒, 而你想自定義一個接收一個強制位置參數(shù)的構(gòu)造函數(shù)。那樣你就需要自定義 new方法搪泳。要創(chuàng)建一個對象, 被重寫的 new 方法中必須調(diào)用 self.bless

class C {
    has $.size;
    method new($x) {
        self.bless(*, size => 2 * $x);
    }
}

say C.new(3).size; # 接收一個位置參數(shù), 打印出 6

bless的第一個參數(shù) *****號告訴它創(chuàng)建一個空對象自身稀轨。

如果你想開啟額外的具名參數(shù), 那很容易:

class C {
    has $.size;
    method new($x, *%remaining) {
        self.bless(*, size => 2 * $x, |%remaining);
    }
}

注意, 這兩個概念(自定義 new() 和 BUILD() (sub)methods) 是正交的; 你一次可以使用它倆, 它倆能和諧共處。

屬性的默認(rèn)值


為屬性提供默認(rèn)值的最方便的方式是在聲明屬性的時候為屬性提供默認(rèn)值:

class Window {
    has $.height = 600;
    has $.width  = $.height * 1.618;
    ...
}

默認(rèn)值只會用在底層屬性沒有被 newBUILD接觸的時候使用森书。

理解對象初始化


假如你有一個類 C 繼承自類 B, 那么創(chuàng)建一個類 C 的對象的處理看起來是這樣:

img

用戶調(diào)用 C.new, 這反過來調(diào)用 self.bless(*, |args)靶端。bless 方法創(chuàng)建了一個新的存儲新創(chuàng)建對象的 P6Opaque 對象谎势。這就是調(diào)用上圖中的 CREATE凛膏。

分配完存儲空間和屬性初始化之后, new把控制權(quán)傳給BUILDALL(順帶傳遞所有的具名參數(shù)), 這反過來會從層級樹的頂端開始, 調(diào)用繼承層級樹上所有類的 BUILD 方法, 最后調(diào)用類 C 的 BUILD 方法。

這樣的設(shè)計允許你花費最少的力氣來替換初始化的一部分, 尤其是自定義 newBUILD 方法會很容易寫脏榆。

use v6;

class B {
    has $.name;

    submethod BUILD(:$!name) {
        say "調(diào)用了 B 的 BUILD, 我叫 $!name"
    }
}

class C is B {
    has $.nickname;

    submethod BUILD(:$!nickname, :$name) {
        say "調(diào)用了 C 的 BUILD, 我叫 $!nickname, 我爸爸是 $name"
    }
    method new(:$nickname) {
        self.bless(nickname => 'Camelia', name => 'Lucy');
    }
}

my $c = C.new(nickname => 'HANMEIMEI');

打硬痢:

調(diào)用了 B 的 BUILD, 我叫 Lucy
調(diào)用了 C 的 BUILD, 我叫 Camelia, 我爸爸是 Lucy
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市须喂,隨后出現(xiàn)的幾起案子吁断,更是在濱河造成了極大的恐慌,老刑警劉巖坞生,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仔役,死亡現(xiàn)場離奇詭異,居然都是意外死亡是己,警方通過查閱死者的電腦和手機又兵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來卒废,“玉大人沛厨,你說我怎么就攤上這事∷と希” “怎么了逆皮?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長参袱。 經(jīng)常有香客問我电谣,道長秽梅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任剿牺,我火速辦了婚禮风纠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘牢贸。我一直安慰自己竹观,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布潜索。 她就那樣靜靜地躺著臭增,像睡著了一般。 火紅的嫁衣襯著肌膚如雪竹习。 梳的紋絲不亂的頭發(fā)上誊抛,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機與錄音整陌,去河邊找鬼拗窃。 笑死,一個胖子當(dāng)著我的面吹牛泌辫,可吹牛的內(nèi)容都是我干的随夸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼震放,長吁一口氣:“原來是場噩夢啊……” “哼宾毒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起殿遂,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤诈铛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后墨礁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體幢竹,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年恩静,在試婚紗的時候發(fā)現(xiàn)自己被綠了焕毫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜕企,死狀恐怖咬荷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情轻掩,我是刑警寧澤幸乒,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站唇牧,受9級特大地震影響罕扎,放射性物質(zhì)發(fā)生泄漏聚唐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一腔召、第九天 我趴在偏房一處隱蔽的房頂上張望杆查。 院中可真熱鬧,春花似錦臀蛛、人聲如沸亲桦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽客峭。三九已至,卻和暖如春抡柿,著一層夾襖步出監(jiān)牢的瞬間舔琅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工洲劣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留备蚓,地道東北人。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓囱稽,卻偏偏與公主長得像郊尝,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子粗悯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理虚循,服務(wù)發(fā)現(xiàn),斷路器样傍,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,970評論 6 13
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法铺遂,內(nèi)部類的語法衫哥,繼承相關(guān)的語法,異常的語法襟锐,線程的語...
    子非魚_t_閱讀 31,631評論 18 399
  • Object Orientation in Perl 6 Perl 6 有很多預(yù)先定義好的類型撤逢,這些類型可以歸為 ...
    焉知非魚閱讀 468評論 0 1
  • 遠(yuǎn)方響起蒼茫的馬蹄 我在湖邊等你 等你為我披上衣 湖面陣陣漣漪 是你走過留下的的足跡 你如白蓮花 自水中升起 問候...
    柳曉生閱讀 164評論 0 1