Perl5 OOP學習筆記
更新時間:2009年04月25日 02:07:46 作者:
在Perl排名持續(xù)下降的情況下學Perl,似乎是有點不明智。但是,工作需要,不得不學啊。再說,Perl現(xiàn)在在測試領(lǐng)域還是用得非常多的。Phython雖然也在測試領(lǐng)域開始活躍起來,不過我始終還是不太喜歡Phython的語法。
復制代碼 代碼如下:
# test.pl
package MyClass;
sub new {
my $this = {};
bless($this);
}
package main;
my $obj1 = MyClass::new();
my $obj2 = MyClass->new();
my $obj3 = new MyClass();
print(join("\n", ref($obj1), ref($obj2), ref($obj3)));
__END__
MyClass
MyClass
MyClass
注意上面new MyClass()的效果和MyClass->new()效果是一樣的。這里new不是關(guān)鍵字,而是函數(shù)名。同理,如果有一個foo成員函數(shù)的話,也可以foo MyClass(args),它實際上是MyClass::foo(MyClass, args);
話說回來,如果需要初始化對象數(shù)據(jù)又該如何呢?前面說過,對象數(shù)據(jù)保存在引用的數(shù)據(jù)自身,所以我們通常是把一個Hash引用bless成對象。所以我們經(jīng)常會看到這樣調(diào)用new:
復制代碼 代碼如下:
my $obj = MyClass->new('key1' => 'value1', 'key2' => 'value2');
或者
復制代碼 代碼如下:
my $obj = MyClass->new({'key1' => 'value1', 'key2' => 'value2'});
兩種調(diào)用方式的區(qū)別在于new函數(shù)中的處理不同,因為前者傳入的是一個Hash實體,而后者傳入的是一個Hash引用。為了兼容這兩種情況,new函數(shù)通常會像下面程序中的寫法:
復制代碼 代碼如下:
# test.pl
package MyClass;
sub new {
my $class = shift();
my $this = ref(@_[0]) ? @_[0] : {@_};
bless($this);
}
package main;
use Data::Dumper;
my $obj1 = MyClass->new('name' => 'James Fancy', 'age' => 30);
my $obj2 = MyClass->new({'name' => 'James Fancy', 'age' => 30});
print(Dumper($obj1));
print(Dumper($obj2));
__END__
$VAR1 = bless( {
'name' => 'James Fancy',
'age' => 30
}, 'MyClass' );
$VAR1 = bless( {
'name' => 'James Fancy',
'age' => 30
}, 'MyClass' );
訪問對象數(shù)據(jù)
既然通常是Hash引用被bless成對象,那就只說這種情況。
既然是Hash引用,所以訪問數(shù)據(jù)最簡單的辦法就跟訪問Hash引用一樣。比如
復制代碼 代碼如下:
$obj->{'name'} = "You Name";
my $name = $obj->{'name'};
$obj->{'name'} = "You Name";
my $name = $obj->{'name'};
如果想少寫點花括號,可以通過定義setter/getter的辦法來解決。因為getter和setter可以根據(jù)有沒參數(shù)來區(qū)分,所以合并在一個函數(shù)中成為可能,比如下面的name函數(shù)
復制代碼 代碼如下:
# test.pl
package MyClass;
sub new {
my $class = shift();
my $this = ref(@_[0]) ? @_[0] : {@_};
bless($this);
}
sub name {
my $this = shift();
if (@_[0]) {
$this->{'name'} = @_[0];
}
return $this->{'name'};
}
package main;
my $obj = MyClass->new('name' => 'James Fancy');
print($obj->name, "\n");
print($obj->name("New Name"), "\n");
__END__
James Fancy
New Name
# test.pl
package MyClass;
sub new {
my $class = shift();
my $this = ref(@_[0]) ? @_[0] : {@_};
bless($this);
}
sub name {
my $this = shift();
if (@_[0]) {
$this->{'name'} = @_[0];
}
return $this->{'name'};
}
package main;
my $obj = MyClass->new('name' => 'James Fancy');
print($obj->name, "\n");
print($obj->name("New Name"), "\n");
__END__
James Fancy
New Name
使用setter/getter的確可以使程序看起來簡潔不少。但是對對象中的每個數(shù)據(jù)寫一個getter/setter,還是很累人的,于是,AUTOLOAD函數(shù)就被抬出來了,看看下面的程序
復制代碼 代碼如下:
package MyClass;
sub new {
my $class = shift();
my $this = ref(@_[0]) ? @_[0] : {@_};
bless($this, $class);
}
sub AUTOLOAD {
my $this = $_[0];
if (!ref($this)) {
return;
}
my $name = $AUTOLOAD;
if (defined($name)) {
$name =~ s/.*:://;
} else {
return;
}
my $class = ref($this);
if (defined($this->{$name}) || @_) {
no strict 'refs';
*{"${class}::$name"} = sub {
my $this = shift();
$this->{$name} = shift() if (@_);
# make a property in hash reference type to HashObject object.
if (ref($this->{$name}) eq 'HASH') {
bless($this->{$name}, $class);
}
return $this->{$name};
};
goto &$name;
}
}
package main;
my $obj = MyClass->new('name' => 'James Fancy');
$obj->more1({'key', 'value of more1->key'});
print($obj->name, "\n");
print($obj->more1->key, "\n");
print($obj->more2({})->key("value of more2->key"), "\n");
__END__
James Fancy
value of more1->key
value of more2->key
這樣調(diào)用起來是不是方便多了?不過AUTOLOAD寫起來很累人的。如果你只需要一個數(shù)據(jù)對象,網(wǎng)上有個Hash::AsObject的類很好用,用法和上面的最后一個示例差不多。
繼承
我的確是對繼承這個方面沒怎么研究。不過簡單的繼承大概就是用use base語句引入基類而已,比如
復制代碼 代碼如下:
package Parent;
sub test1 {
print("Parnet::test1\n");
}
sub test {
print("Parent::test\n");
}
package Sub;
use base Parent;
sub test {
print("Sub::test\n");
}
sub test2 {
$_[0]->Parent::test();
}
package main;
my $obj = bless({}, *Sub);
$obj->test();
$obj->test1();
$obj->test2();
__END__
Sub::test
Parnet::test1
Parent::test
參考資料
東南大學出版社出版,O'Reilly的《精通Perl(影印版)》,brian d foy著
Perl version 5.10.0 documentation,http://perldoc.perl.org/
Hash::AsObject源碼,來自http://search.cpan.org/~nkuitse/Hash-AsObject-0.11/lib/Hash/AsObject.pm
相關(guān)文章
Perl使用nginx FastCGI環(huán)境做WEB開發(fā)實例
這篇文章主要介紹了Perl使用nginx FastCGI環(huán)境做WEB開發(fā)實例,實現(xiàn)了路由系統(tǒng)和模板系統(tǒng),需要的朋友可以參考下2014-06-06perl控制流介紹(if條件,while,for循環(huán),foreach)
Perl控制流(if條件,while,for循環(huán)),需要的朋友可以參考下2013-02-02Perl中的符號 ->;、=>; 和 :: 分別表示什么意思?
這篇文章主要介紹了Perl中的符號 ->;、=>; 和 :: 分別表示什么意思,需要的朋友可以參考下2017-10-10