perl繼承的那些事

Perl類的繼承是通過@ISA數(shù)組實(shí)現(xiàn)的矩欠。@ISA數(shù)組不需要在任何包中定義猾蒂,然而,一旦它被定義隐孽,Perl就把它看作目錄名的特殊數(shù)組癌椿。它與@INC數(shù)組類似,@INC是包含文件的尋找路徑菱阵。@ISA數(shù)組含有類(包)名踢俄,當(dāng)一個(gè)方法在當(dāng)前包中未找到時(shí)就到@ISA中的包去尋找。@ISA中還含有當(dāng)前類繼承的基類名晴及。
類中調(diào)用的所有方法必須屬于同一個(gè)類或@ISA數(shù)組定義的基類褪贵。如果一個(gè)方法在@ISA數(shù)組中未找到,Perl就到AUTOLOAD()子程序中尋找抗俄,這個(gè)可選的子程序在當(dāng)前包中用sub定義。若使用AUTOLOAD子程序世舰,必須用use Autoload;語句調(diào)用autoload.pm包动雹。AUTOLOAD子程序嘗試從已安裝的Perl庫(kù)中裝載調(diào)用的方法。如果AUTOLOAD也失敗了跟压,Perl再到UNIVERSAL類做最后一次嘗試胰蝠,如果仍失敗,Perl就生成關(guān)于該無法解析函數(shù)的錯(cuò)誤震蒋。
perl中有兩種不同地面向?qū)ο缶幊痰膶?shí)現(xiàn):
1.基于匿名哈希表的方式茸塞,每個(gè)對(duì)象實(shí)例的實(shí)質(zhì)就是指向匿名哈希表的引用。在這個(gè)匿名哈希表中查剖,存儲(chǔ)來所有的實(shí)例屬性钾虐。
2.基于數(shù)組的方式。定義一個(gè)類時(shí)笋庄,我們將為每一個(gè)實(shí)例創(chuàng)建一個(gè)數(shù)組效扫,而每一個(gè)對(duì)象實(shí)例的實(shí)質(zhì)就是指向這些數(shù)組中某一行索引的引用倔监。在這些數(shù)組中,存儲(chǔ)著所有的實(shí)例屬性菌仁。

面向?qū)ο蟮母拍?##

實(shí)例:一個(gè)對(duì)象的實(shí)例化實(shí)現(xiàn)浩习。
標(biāo)識(shí):每個(gè)對(duì)象的實(shí)例都需要一個(gè)可以唯一標(biāo)識(shí)這個(gè)實(shí)例的標(biāo)記。
實(shí)例屬性:一個(gè)對(duì)象就是一組屬性的集合济丘。
實(shí)例方法:所有存取或者更新對(duì)象某個(gè)實(shí)例一條或者多條屬性的函數(shù)集合谱秽。
類屬性:屬于一個(gè)類中所有對(duì)象的屬性,不會(huì)只在某個(gè)實(shí)例上發(fā)生變化摹迷。
類方法:那些無需特定的對(duì)象實(shí)例就能工作的從屬于類的函數(shù)疟赊。

基于匿名散列表的實(shí)現(xiàn)###

首先,我們需要定義一個(gè)匿名散列表泪掀,并用一個(gè)引用指向這個(gè)匿名散列表听绳,如清單1所示,我們定義了一個(gè)初始化函數(shù)來封裝這個(gè)匿名散列表的初始化過程异赫。這個(gè)函數(shù)接受參數(shù)作為初始值椅挣,并引用這些初始值初始化其內(nèi)部包含的匿名哈希表,并且返回一個(gè)指向這個(gè)匿名哈希表的引用塔拳。

package Person;
sub new{
   my ($name,$age) = @_;
   my $_self = {
       "name" => $name,
       "age"    => $age,
   };
   return $_self;
}
my $p_obj1 = Person->new('Tony',23);
my $p_obj2 = Person->new('Tommy',30);
print "Person1's name : " . $p_obj1->{name} . "age: " . $p_obj1->{age} . ".\n" ;
print "Person2's name : " .  $p_obj2->{name} . "age: " . $p_obj2->{age} . ".\n";

此方案有一個(gè)致命的問題鼠证,perl的編譯器并不知道new函數(shù)所返回的指向匿名哈希表的引用屬于哪個(gè)類。所以靠抑,在清單2中量九,如果要使用類中的實(shí)例方法,只能直接標(biāo)出方法所屬的類的名字颂碧,并將引用作為方法的第一個(gè)參數(shù)傳遞給它荠列。

package Person;
...
sub change_name{
   my ($self,$new_name) = @_;
   $self->{name} = $new_name;
}

my $p_obj = Person->new("tony",23);
print "Person's name :" . $p_obj->{name} . ".\n";
Person::change_name($p_obj,"Tommy");
print "Person's new name : " . $p_obj->{name}. ".\n";

解決這個(gè)問題的關(guān)鍵是引入bless。bless以一個(gè)普通的指向數(shù)據(jù)結(jié)構(gòu)的引用為參數(shù)载城,它將會(huì)把那個(gè)數(shù)據(jù)結(jié)構(gòu)(不是引用本身)標(biāo)記為屬于某個(gè)特定的包肌似。這樣就賦予了這個(gè)匿名哈希表的引用以多態(tài)的能力。同時(shí)诉瓦,我們使用箭頭記號(hào)來直接調(diào)用那些實(shí)例方法川队。
以下清單中的“bless($self)”,將指向一個(gè)匿名哈希表的引用標(biāo)記為屬于當(dāng)前包睬澡,也就是package Person固额。所以當(dāng)Perl看到"$p_obj->change_name($name)"時(shí),它會(huì)決定$p_obj屬于package Person煞聪。
Perl會(huì)如下所示地調(diào)用這個(gè)函數(shù)斗躏,“Person::change_name($p_obj,$name)”,和清單2的第一種實(shí)現(xiàn)一樣,換而言之昔脯,如果使用箭頭的方式調(diào)用一個(gè)函數(shù)瑟捣,箭頭左邊的那個(gè)對(duì)象將作為相應(yīng)子程序的第一個(gè)參數(shù)馋艺,Perl的實(shí)例方法本質(zhì)就是一個(gè)第一個(gè)參數(shù)碰巧為對(duì)象引用的子程序。

package Person
sub new{
    my $self = {};
    shift;
    my ($name,$age) = @_;
    $self->{name}  = $name;
    $self->{age}   =$age;
     bless($self);
     return $self;
}
sub change_name{
     my $self = shift;
     my $name = shift;
     $self->{name}  = $name;
}
my $p_obj = Person->new("David", 27);
print "Name:" . $p_obj->{name} . ".\n";
$p_obj->change_name("Tony");
print "Name: " . $p_obj->{name}. "\n";

Perl的這種調(diào)用相應(yīng)模塊函數(shù)的能力被稱作運(yùn)行時(shí)聯(lián)編迈套。調(diào)用過new方法之后捐祠,返回一個(gè)匿名哈希表的引用,并且包含相應(yīng)類的名字桑李。
Perl中并沒有針對(duì)類屬性和類方法的特定語法踱蛀。類屬性只是包中的全局變量,而類方法則是不依賴于任何特定實(shí)例的子程序贵白。以下清單是一個(gè)關(guān)于類屬性和類方法的例子率拒。與實(shí)例方法不同,我們使用Person::calculate_person_number()的形勢(shì)來調(diào)用類方法禁荒。這樣的話猬膨,指向匿名哈表的引用將不會(huì)做為第一個(gè)調(diào)用參數(shù)傳入,我們與不需要在包的子程序附加處理傳入引用的代碼呛伴。
清單4:基于匿名哈希表的面向?qū)ο缶幊讨械念惙椒ㄅc類屬性

my $person_number = 0;
...
sub new{
     $person_number++;
}
sub calculate_person_number{
    return $person_number;
}
my $p_obj1 = Person->new("David", 27);
my $p_obj2 = Person->new("Tonny", 27);
my $person_number = Person::calculate_person_number();
print "We have ". $person_number . " persons in all.\n";

基于匿名哈希表的方法中的繼承###

Perl允許一個(gè)模塊在一個(gè)特殊的名為@ISA的數(shù)組中指定一組其他模塊的名稱勃痴。當(dāng)在模塊中找不到某個(gè)實(shí)例方法時(shí),它就為檢查那個(gè)模塊 的@ISA是否被初始化热康。如果已經(jīng)初始化了 沛申,他就會(huì)檢查其中的某個(gè)模塊是否支持這個(gè)“缺少”的函數(shù)。如果它按照深度優(yōu)先的層次結(jié)構(gòu)搜索@ISA數(shù)組并且發(fā)現(xiàn)同名的方法姐军,它會(huì)調(diào)用第一個(gè)被發(fā)現(xiàn)的同名方法并且將控制權(quán)交給它铁材,我們利用perl的這個(gè)特性實(shí)現(xiàn)繼承。
考慮這樣一個(gè)類的層次奕锌,我們定義一個(gè)Employee類著觉,繼承于基站類的Person,如清單5所示惊暴。

我們將類名Person放入包Employee的ISA數(shù)組中饼丘,這樣調(diào)用一個(gè)在包Employee中沒有定義的函數(shù)時(shí),Perl編譯器就會(huì)自動(dòng)在Person類中尋找這個(gè)函數(shù)缴守,當(dāng)用戶調(diào)用new函數(shù)初始化一個(gè)employee實(shí)例對(duì)象的時(shí)候,Employee的new函數(shù)會(huì)在內(nèi)部調(diào)用它的基類的new函數(shù)镇辉,并且返回一個(gè)包含部分以初始化的基類實(shí)例屬性的匿名哈希表屡穗。接著Employee的new函數(shù)將繼續(xù)執(zhí)行new函數(shù)的剩余代碼,完成屬于Employee自身的初始化工作忽肛,為Employee剩余的實(shí)例屬性賦值村砂。
清單5.基于匿名哈希表的面向?qū)ο缶幊讨械睦^承

use Person;
package Employee;
@ISA = qw( Person );
sub new{
    shift;
    my ($name,$age,$salary) = @_;
    my $self = Person->new($name,$age);
    $self->{salary}  =$salary;
    bless ($self);
    return $self;
}

sub change_salary{
    my $self = shift;
    my $new_salary = shift;
    $self->{salary}   = $new_salary;
}
my $p_obj =Employee->new("Tonny", 28,10000);
print "Name: " . $p_obj->{name} . "Age: " . $p_obj->{age} . 
",Salary: " . $p_obj->{salary} . " . \n";
$p_obj->change_name("Tommy");
$p_obj->change_salary(13000);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市屹逛,隨后出現(xiàn)的幾起案子础废,更是在濱河造成了極大的恐慌汛骂,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件评腺,死亡現(xiàn)場(chǎng)離奇詭異帘瞭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蒿讥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門蝶念,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人芋绸,你說我怎么就攤上這事媒殉。” “怎么了摔敛?”我有些...
    開封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵廷蓉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我马昙,道長(zhǎng)桃犬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任给猾,我火速辦了婚禮疫萤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘敢伸。我一直安慰自己扯饶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開白布池颈。 她就那樣靜靜地躺著尾序,像睡著了一般。 火紅的嫁衣襯著肌膚如雪躯砰。 梳的紋絲不亂的頭發(fā)上每币,一...
    開封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音琢歇,去河邊找鬼兰怠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛李茫,可吹牛的內(nèi)容都是我干的揭保。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼魄宏,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼秸侣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤味榛,失蹤者是張志新(化名)和其女友劉穎椭坚,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體搏色,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡善茎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了继榆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巾表。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖略吨,靈堂內(nèi)的尸體忽然破棺而出集币,到底是詐尸還是另有隱情,我是刑警寧澤翠忠,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布鞠苟,位于F島的核電站,受9級(jí)特大地震影響秽之,放射性物質(zhì)發(fā)生泄漏当娱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一考榨、第九天 我趴在偏房一處隱蔽的房頂上張望跨细。 院中可真熱鬧,春花似錦河质、人聲如沸冀惭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)散休。三九已至,卻和暖如春乐尊,著一層夾襖步出監(jiān)牢的瞬間戚丸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工扔嵌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留限府,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓痢缎,卻偏偏與公主長(zhǎng)得像胁勺,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子牺弄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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