<pre name="code" class="html">https://www.ibm.com/developerworks/cn/linux/l-cn-perlobj/
Perl 面向对象编程的两种实现和比较:
Perl 面向对象的实现有两种方式:
1.基于匿名散列
2.基于数组
Perl 作为一种成熟的“面向过程”的语言,同样也提供了对于面向对象编程的支持。
Perl 中有两种不同地面向对象编程的实现,一是基于匿名哈希表的方式,每个对象实例的实质就是一个指向匿名哈希表的引用。
在这个匿名哈希表中,存储来所有的实例属性。二是基于数组的方式,在定义一个类的时候,我们将为每一个实例属性创建一个数组,
而每一个对象实例的实质就是一个指向这些数组中某一行索引的引用。在这些数组中,存储着所有的实例属性。
面向对象的概念
实例 (instance):一个对象的实例化实现。
标识 (identity):每个对象的实例都需要一个可以唯一标识这个实例的标记。
实例属性 (instance attribute):一个对象就是一组属性的集合。
实例方法 (instance method):所有存取或者更新对象某个实例一条或者多条属性的函数的集合。
类属性(class attribute):属于一个类中所有对象的属性,不会只在某个实例上发生变化。
类方法(class method):那些无须特定的对性实例就能够工作的从属于类的函数。
基于匿名散列表的方法:
[root@wx03 test]# cat Person.pm
package Person;
sub new {
my ($class,$name, $age) = @_; ##第一个参数为类名
my $r_object = {
"name" => $name,
"age" => $age
};
return $r_object;
};
sub change_name {
my ($self, $new_name) = @_; ##第一个参数为对象
$self->{name} = $new_name;
}
1;
[root@wx03 test]# cat t15.pl
unshift(@INC,"/root/test");
use Person;
my $object_person = Person->new( "Tommy", "22" );
use Data::Dumper;
my $var = Dumper($object_person);
print $var;
print $object_person->{"name"};
print "\n";
print $object_person->{"age"};
print "\n";
Person::change_name ($object_person, "Tonny" );
print $object_person->{"name"};
print "\n";
[root@wx03 test]# perl t15.pl
$VAR1 = {
'name' => 'Tommy',
'age' => '22'
};
Tommy
22
Tonny
[root@
但是,现在的这个方案有一个致命的缺点,Perl 的编译器并不知道如何 new 函数所返回的指向匿名哈希表的引用属于哪个类(模块)。这样的话,如果要使用类中的实例方法,只能直接标出方法所属于的类(模块)的名字,并将引用作为方法的第一个参数传递给它,如清单 2 所示。
bless 以一个普通的指向数据结构的引用为参数,它将会把那个数据结构(注意:此处不是引用本身)标记为属于某个特定的包,
这样就赋予了这个匿名哈希表的引用以多态的能力。同时,我们使用箭头记号来直接调用那些实例方法
换而言之,如果使用箭头的方式调用一个函数,箭头左边的那个对象将作为相应子例程的第一个参数。 Perl 的实例方法的本质其实就是一个第一个参数碰巧为对象引用的普通子例程
类方法则是不依赖于任何特定实例的普通子例程。
与实例方法不同,我们使用 Person::calculate_person_number () 的形势来调用类方法。这样的话,指向匿名哈希表的引用将不会作为第一个调用参数传入,我们与不需要在包的子例程附加处理传入引用的代码。
类方法不需要对象作为第一个参数
[root@wx03 test]# cat Person.pm
package Person;
sub new {
my ($class,$name, $age) = @_;
my $r_object = {
"name" => $name,
"age" => $age
};
return $r_object;
};
sub change_name {
my ($self, $new_name) = @_;
$self->{name} = $new_name;
};
sub calculate_person_number {
return 999;
} ;
1;
//访问类方法;
[root@wx03 test]# cat t16.pl
unshift(@INC,"/root/test");
use Person;
my $person_number = Person::calculate_person_number();
print "\$person_number is $person_number\n";
[root@wx03 test]# perl t16.pl
$person_number is 999
基于匿名散列表的方法中的继承:
考虑这样一个类的层次,我们定义一个 Employee 类,继承于基类 Person:
Employee 类继承Person类:
我们将类名Person 放入包Emoloyee的ISA数组里,
这样当调用一个在包Employee中没有定义的函数时,Perl编译器会自动
在Person类寻找这个函数。