欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Perl5 OOP學(xué)習(xí)筆記第1/2頁(yè)

 更新時(shí)間:2009年04月25日 02:07:46   作者:  
在Perl排名持續(xù)下降的情況下學(xué)Perl,似乎是有點(diǎn)不明智。但是,工作需要,不得不學(xué)啊。再說(shuō),Perl現(xiàn)在在測(cè)試領(lǐng)域還是用得非常多的。Phython雖然也在測(cè)試領(lǐng)域開(kāi)始活躍起來(lái),不過(guò)我始終還是不太喜歡Phython的語(yǔ)法。
在學(xué)習(xí)了Perl的基本語(yǔ)法之后,學(xué)習(xí)Perl的OOP,略有心得。不知道Perl各個(gè)版本之間OOP是否有區(qū)別,但是我是學(xué)習(xí)的Perl5,所以在標(biāo)題上將版本號(hào)也寫(xiě)出來(lái)了。因?yàn)榱私獾絇HP4和PHP5的OOP部分就有不小的差別,所以有此擔(dān)心。
  學(xué)習(xí)Perl的OOP,最關(guān)鍵的兩件事情就是package和bless。只要把這兩個(gè)東西搞清楚也就學(xué)會(huì)大一半了。
Perl的package
  感覺(jué)Perl的package和Java還真有點(diǎn)相似。Java的package是以CLASSPATH中的目錄為根,按目錄定義和搜索分級(jí)包名。Perl也類(lèi)似,是以@INC數(shù)組中的目錄為根,按目錄搜索分級(jí)包名。不過(guò)有一點(diǎn)不同,Perl的package定義貌似不需要與目錄結(jié)構(gòu)對(duì)應(yīng)。具體是什么樣的規(guī)則我沒(méi)有去研究,因?yàn)榘茨夸浗Y(jié)構(gòu)定義package是個(gè)好習(xí)慣。
  相較于Java,Perl的package還有一點(diǎn)很有意思。Java的每層package對(duì)應(yīng)一個(gè)目錄,而最后是一個(gè)class文件對(duì)應(yīng)到類(lèi)名。Perl卻簡(jiǎn)化了,package直接就把目錄和文件名都引用了進(jìn)去。比如
  Java中,name.jamesfancy.MyClass,對(duì)應(yīng)的是/name/jamesfancy/MyClass.class,源代碼中則分成兩句來(lái)寫(xiě)
復(fù)制代碼 代碼如下:

package name.jamesfancy;
class MyClass {....}
package name.jamesfancy;
class MyClass {....}

  Perl中,name::jamesfancy::MyClass,應(yīng)對(duì)的是/name/jamesfancy/MyClass.pm,源代碼中只有一句package就說(shuō)明了
復(fù)制代碼 代碼如下:

package name::jamesfancy::MyClass;
package name::jamesfancy::MyClass;

  至于package中的內(nèi)容,也就是變量和子程序,至于區(qū)別,稍后再說(shuō)。
bless函數(shù)
  bless是用來(lái)把一個(gè)類(lèi)綁定到引用類(lèi)型變量的函數(shù)。很奇怪Perl為什么要用這個(gè)單詞,不過(guò)沒(méi)關(guān)系,我們可以把它想像得形象一點(diǎn):就像游戲里牧師通過(guò)祝福技能為某人加上BUFF一樣,bless把一個(gè)類(lèi)綁定到某個(gè)引用類(lèi)型的變量,從此這個(gè)變量就受到了祝福,擁有了這個(gè)類(lèi)中的變量和子程序。
  bless的用法通常是:bless($引用變量, 類(lèi)名);
  引用變量貌似可以是任何引用類(lèi)型的變量,我嘗試過(guò)Scalar,Array和Hash的引用,都能成功。在bless之外,這個(gè)引用變量就可以被稱之為對(duì)象了,當(dāng)然它仍然是個(gè)引用,是對(duì)象的引用。
  有一點(diǎn)還需要注意,雖然這個(gè)對(duì)象擁有了類(lèi)的變量和子程序,但我們應(yīng)該把它擁有的類(lèi)的變量和子程序都看成是靜態(tài)的,換句話說(shuō),就是類(lèi)的成員。在這一點(diǎn)上,子程序的處理會(huì)比較特殊一點(diǎn),但至少類(lèi)的變量,也就是包變量,是不屬于對(duì)象的。因此,所有對(duì)象的數(shù)據(jù)都保存在對(duì)象引用的原始數(shù)據(jù)中。既然大家都習(xí)慣對(duì)象數(shù)據(jù)以鍵值對(duì)的方式保存,所以通常情況下,bless的引用變量,都是Hash的引用了。
  很抽象么?舉個(gè)例子。如果對(duì)OOP的成員函數(shù)還不夠了解,那就只看下面示例中每個(gè)類(lèi)的test函數(shù)中第一句以后的內(nèi)容不好。
復(fù)制代碼 代碼如下:

# test.pl
package TestScalar;
sub test {
my $this = shift();
print("\nIn TestScalar::test()\n");
print("Scalar:\n ${$this}\n");
}

package TestArray;
sub test {
my $this = shift();
print("\nIn TestArray::test()\n");
print("Array:\n");
foreach my $item (@{$this}) {
print(" $item\n");
}
}

package TestHash;
sub test {
my $this = shift();
print("\nIn TestHash::test()\n");
print("Hash:\n");
while (my ($key, $value) = each %{$this}) {
printf(" %-4s = %s\n", $key, $value);
}
}

package main;

my $name = "James Fancy";
my $objScalar = \$name;
my $objArray = ['James', 'Fancy', 'Jenny'];
my $objHash = {'name' => 'James', 'age' => 30};

bless($objScalar, 'TestScalar');
bless($objArray, 'TestArray');
bless($objHash, 'TestHash');

$objScalar->test();
$objArray->test();
$objHash->test();

__END__

In TestScalar::test()
Scalar:
James Fancy

In TestArray::test()
Array:
James
Fancy
Jenny

In TestHash::test()
Hash:
name = James
age = 30

從上面的示例中可以看到,分別將3種類(lèi)型的引用轉(zhuǎn)變?yōu)閷?duì)象。之所以要把類(lèi)寫(xiě)成3個(gè)而非1個(gè),主要是為了在Test里輸出不同類(lèi)型的數(shù)據(jù)。

類(lèi)和對(duì)象的成員函數(shù)

  成員函數(shù)就是在package中定義的子程序。成員函數(shù)是沒(méi)有靜態(tài)和非靜態(tài)之分的,但我寧愿大家都把它看作是靜態(tài)函數(shù),因?yàn)殡m然它即可以當(dāng)作類(lèi)成員函數(shù)來(lái)調(diào)用,也可以當(dāng)用對(duì)象成員函數(shù)來(lái)調(diào)用,但在當(dāng)作對(duì)象成員函數(shù)來(lái)調(diào)用的時(shí)候,Perl偷偷的傳入了對(duì)象引用。這也解釋了為什么通常成員函數(shù)里的第一句話往往是

復(fù)制代碼 代碼如下:

my $this = shift();

當(dāng)然,這里的$this只是一個(gè)局部變量,而不是關(guān)鍵字,你也可以用別的名稱來(lái)代替它。比如很多人就喜歡用$self,或者$me等。
假如,對(duì)于一個(gè)成員函數(shù),分別用類(lèi)和對(duì)象來(lái)對(duì)它進(jìn)行調(diào)用,會(huì)有什么不一樣呢?再看一個(gè)示例:
復(fù)制代碼 代碼如下:

# test.pl
package MyClass;

sub test {
my ($this, @args) = @_;
print('-' x 40, "\n");
print("\$this is [$this], Ref of \$this is [", ref($this), "]\n");
print("Args: [@args]\n");
}

package main;

$obj = {};
bless($obj, 'MyClass');

MyClass->test("MyClass->test(...)");
$obj->test("\$obj->test(...)");

__END__
----------------------------------------
$this is [MyClass], Ref of $this is []
Args: [MyClass->test(...)]
----------------------------------------
$this is [MyClass=HASH(0x178a44)], Ref of $this is [MyClass]
Args: [$obj->test(...)]

從結(jié)果可以看出來(lái),不管哪種方法調(diào)用,第一個(gè)參數(shù)都是Perl偷偷傳遞進(jìn)去的。如果是類(lèi)調(diào)用,則第一個(gè)參數(shù)是該類(lèi)。如果是對(duì)象調(diào)用,第一個(gè)參數(shù)是該對(duì)象。因此,只需要將ref($this)的結(jié)果和類(lèi)名進(jìn)行比較就清楚是哪種調(diào)用了。所以,一個(gè)容錯(cuò)性較好的成員函數(shù),一開(kāi)始要判斷傳入的第一個(gè)參數(shù),比如
復(fù)制代碼 代碼如下:

sub foo {
my $this = shift();
return unless ($this ne 'MyClass');
# 其它語(yǔ)句
}

這里還有一個(gè)疑問(wèn):既然package中定義的子程序都是成員函數(shù),那不是類(lèi)的package和是類(lèi)的package有啥區(qū)別?它們?cè)诮Y(jié)構(gòu)上沒(méi)有一點(diǎn)區(qū)別,唯一的區(qū)別在處理中。在調(diào)用子程序的時(shí)候,Perl不會(huì)硬塞一個(gè)類(lèi)或者對(duì)象在參數(shù)列表的最前面,但調(diào)用成員函數(shù)的時(shí)候會(huì),所以區(qū)別是根據(jù)你的調(diào)用方式來(lái)區(qū)分的。

  調(diào)用對(duì)象成員還好說(shuō),$obj->foo()就好,但是調(diào)用類(lèi)成員的時(shí)候,怎么知道是調(diào)用的類(lèi)成員還是包中的子程序呢?那就要看是通過(guò)“->”還是“::”來(lái)調(diào)用的了。下面的例子可以幫助理解:
復(fù)制代碼 代碼如下:

# test.pl
package MyClass;
use Data::Dumper;
sub test {
print('-' x 40, "\n");
print(Dumper(@_));
}

package main;

MyClass->test("MyClass->test(...)");
MyClass::test("MyClass::test(...)");

__END__
----------------------------------------
$VAR1 = 'MyClass';
$VAR2 = 'MyClass->test(...)';
----------------------------------------
$VAR1 = 'MyClass::test(...)';

很明顯,通過(guò)“::”調(diào)用的子程序沒(méi)有被Perl塞入一個(gè)引用類(lèi)的參數(shù)。

構(gòu)造函數(shù)
  Perl的OOP沒(méi)有指定專門(mén)的構(gòu)造函數(shù),所以你可以把任何一個(gè)子程序當(dāng)作構(gòu)造函數(shù),當(dāng)然,重要的是其中的內(nèi)容。既然腳本通常不是寫(xiě)給自己一個(gè)人看的,所以還是按照大家的習(xí)慣,把構(gòu)造函數(shù)取名為new吧。按照多數(shù)OOP語(yǔ)言的習(xí)慣,new函數(shù)通常返回一個(gè)對(duì)象或其引用、指針。所以在Perl中,這個(gè)new函數(shù)要返回一個(gè)對(duì)象引用,理所當(dāng)然地,把bless動(dòng)作包含在new函數(shù)中是個(gè)好習(xí)慣。那么一個(gè)簡(jiǎn)單的new函數(shù)看起來(lái)就像這樣:
復(fù)制代碼 代碼如下:

sub new {
my $this = {};
bless($this);
}

這個(gè)new函數(shù)中產(chǎn)生了一個(gè)Hash引用,bless它,并返回它。如果你疑惑為什么這里沒(méi)有看到return語(yǔ)句,那么建議你去看看關(guān)于子程序中返回值的資料,順便查一下bless函數(shù)的說(shuō)明。來(lái)看看完整的程序了解一下是怎么使用new函數(shù)的。

相關(guān)文章

  • Perl使用nginx FastCGI環(huán)境做WEB開(kāi)發(fā)實(shí)例

    Perl使用nginx FastCGI環(huán)境做WEB開(kāi)發(fā)實(shí)例

    這篇文章主要介紹了Perl使用nginx FastCGI環(huán)境做WEB開(kāi)發(fā)實(shí)例,實(shí)現(xiàn)了路由系統(tǒng)和模板系統(tǒng),需要的朋友可以參考下
    2014-06-06
  • Perl List::Util模塊使用實(shí)例

    Perl List::Util模塊使用實(shí)例

    這篇文章主要介紹了Perl List::Util模塊使用實(shí)例,本文給出掃描符合條件的某個(gè)列表并取出第一個(gè)符合條件的、求1到1000之間的和 、求一組數(shù)字的最大值與最小值等實(shí)用功能代碼,需要的朋友可以參考下
    2015-06-06
  • Perl圖形化包管理工具PPM學(xué)習(xí)使用筆記

    Perl圖形化包管理工具PPM學(xué)習(xí)使用筆記

    這篇文章主要介紹了Perl圖形化包管理工具PPM學(xué)習(xí)使用筆記,本文詳細(xì)講解了什么是PPM、PPM界面的功能按鈕說(shuō)明、PPM如何安裝卸載包等內(nèi)容,需要的朋友可以參考下
    2015-06-06
  • perl大文件讀取處理的模塊介紹

    perl大文件讀取處理的模塊介紹

    perl CPAN中有一個(gè)Tie-File 模塊極大方便了對(duì)大文件的操作
    2013-02-02
  • perl控制流介紹(if條件,while,for循環(huán),foreach)

    perl控制流介紹(if條件,while,for循環(huán),foreach)

    Perl控制流(if條件,while,for循環(huán)),需要的朋友可以參考下
    2013-02-02
  • Perl學(xué)習(xí)基本備忘錄

    Perl學(xué)習(xí)基本備忘錄

    Perl學(xué)習(xí)基本備忘錄,包括perl數(shù)組、命令行執(zhí)行perl語(yǔ)句、perl引號(hào)規(guī)則、變量初始化、perl特殊變量等,有需要的朋友,可以參考下
    2013-02-02
  • Perl初學(xué)筆記之Hello World

    Perl初學(xué)筆記之Hello World

    這篇文章主要介紹了Perl初學(xué)筆記之Hello World,本文是自學(xué)Perl的一篇筆記,本文著重講解了cpan的使用,需要的朋友可以參考下
    2015-06-06
  • Perl5 OOP學(xué)習(xí)筆記

    Perl5 OOP學(xué)習(xí)筆記

    在Perl排名持續(xù)下降的情況下學(xué)Perl,似乎是有點(diǎn)不明智。但是,工作需要,不得不學(xué)啊。再說(shuō),Perl現(xiàn)在在測(cè)試領(lǐng)域還是用得非常多的。Phython雖然也在測(cè)試領(lǐng)域開(kāi)始活躍起來(lái),不過(guò)我始終還是不太喜歡Phython的語(yǔ)法。
    2009-04-04
  • Perl AnyEvent中的watcher實(shí)例

    Perl AnyEvent中的watcher實(shí)例

    這篇文章主要介紹了Perl AnyEvent中的watcher實(shí)例,關(guān)于AnyEvent請(qǐng)參閱的更多介紹請(qǐng)參閱文中的相關(guān)鏈接,需要的朋友可以參考下
    2014-09-09
  • Perl中的符號(hào) ->;、=>; 和 :: 分別表示什么意思?

    Perl中的符號(hào) ->;、=>; 和 :: 分別表示什么意思?

    這篇文章主要介紹了Perl中的符號(hào) ->;、=>; 和 :: 分別表示什么意思,需要的朋友可以參考下
    2017-10-10

最新評(píng)論