Perl5 OOP学习笔记第2/2页

 更新时间:2009年04月25日 02:07:46   作者:  
在Perl排名持续下降的情况下学Perl,似乎是有点不明智。但是,工作需要,不得不学啊。再说,Perl现在在测试领域还是用得非常多的。Phython虽然也在测试领域开始活跃起来,不过我始终还是不太喜欢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不是关键字,而是函数名。同理,如果有一个foo成员函数的话,也可以foo MyClass(args),它实际上是MyClass::foo(MyClass, args);

  话说回来,如果需要初始化对象数据又该如何呢?前面说过,对象数据保存在引用的数据自身,所以我们通常是把一个Hash引用bless成对象。所以我们经常会看到这样调用new:
复制代码 代码如下:

my $obj = MyClass->new('key1' => 'value1', 'key2' => 'value2');

或者
复制代码 代码如下:

my $obj = MyClass->new({'key1' => 'value1', 'key2' => 'value2'});

两种调用方式的区别在于new函数中的处理不同,因为前者传入的是一个Hash实体,而后者传入的是一个Hash引用。为了兼容这两种情况,new函数通常会像下面程序中的写法:
复制代码 代码如下:

# 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' );

访问对象数据
  既然通常是Hash引用被bless成对象,那就只说这种情况。
  既然是Hash引用,所以访问数据最简单的办法就跟访问Hash引用一样。比如
复制代码 代码如下:

$obj->{'name'} = "You Name";
my $name = $obj->{'name'};
$obj->{'name'} = "You Name";
my $name = $obj->{'name'};

  如果想少写点花括号,可以通过定义setter/getter的办法来解决。因为getter和setter可以根据有没参数来区分,所以合并在一个函数中成为可能,比如下面的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
# 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的确可以使程序看起来简洁不少。但是对对象中的每个数据写一个getter/setter,还是很累人的,于是,AUTOLOAD函数就被抬出来了,看看下面的程序
复制代码 代码如下:

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

这样调用起来是不是方便多了?不过AUTOLOAD写起来很累人的。如果你只需要一个数据对象,网上有个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

相关文章

  • Perl使用nginx FastCGI环境做WEB开发实例

    Perl使用nginx FastCGI环境做WEB开发实例

    这篇文章主要介绍了Perl使用nginx FastCGI环境做WEB开发实例,实现了路由系统和模板系统,需要的朋友可以参考下
    2014-06-06
  • Perl List::Util模块使用实例

    Perl List::Util模块使用实例

    这篇文章主要介绍了Perl List::Util模块使用实例,本文给出扫描符合条件的某个列表并取出第一个符合条件的、求1到1000之间的和 、求一组数字的最大值与最小值等实用功能代码,需要的朋友可以参考下
    2015-06-06
  • Perl图形化包管理工具PPM学习使用笔记

    Perl图形化包管理工具PPM学习使用笔记

    这篇文章主要介绍了Perl图形化包管理工具PPM学习使用笔记,本文详细讲解了什么是PPM、PPM界面的功能按钮说明、PPM如何安装卸载包等内容,需要的朋友可以参考下
    2015-06-06
  • perl大文件读取处理的模块介绍

    perl大文件读取处理的模块介绍

    perl CPAN中有一个Tie-File 模块极大方便了对大文件的操作
    2013-02-02
  • perl控制流介绍(if条件,while,for循环,foreach)

    perl控制流介绍(if条件,while,for循环,foreach)

    Perl控制流(if条件,while,for循环),需要的朋友可以参考下
    2013-02-02
  • Perl学习基本备忘录

    Perl学习基本备忘录

    Perl学习基本备忘录,包括perl数组、命令行执行perl语句、perl引号规则、变量初始化、perl特殊变量等,有需要的朋友,可以参考下
    2013-02-02
  • Perl初学笔记之Hello World

    Perl初学笔记之Hello World

    这篇文章主要介绍了Perl初学笔记之Hello World,本文是自学Perl的一篇笔记,本文着重讲解了cpan的使用,需要的朋友可以参考下
    2015-06-06
  • Perl5 OOP学习笔记

    Perl5 OOP学习笔记

    在Perl排名持续下降的情况下学Perl,似乎是有点不明智。但是,工作需要,不得不学啊。再说,Perl现在在测试领域还是用得非常多的。Phython虽然也在测试领域开始活跃起来,不过我始终还是不太喜欢Phython的语法。
    2009-04-04
  • Perl AnyEvent中的watcher实例

    Perl AnyEvent中的watcher实例

    这篇文章主要介绍了Perl AnyEvent中的watcher实例,关于AnyEvent请参阅的更多介绍请参阅文中的相关链接,需要的朋友可以参考下
    2014-09-09
  • Perl中的符号 ->;、=>; 和 :: 分别表示什么意思?

    Perl中的符号 ->;、=>; 和 :: 分别表示什么意思?

    这篇文章主要介绍了Perl中的符号 ->;、=>; 和 :: 分别表示什么意思,需要的朋友可以参考下
    2017-10-10

最新评论