http://blog.chinaunix.net/uid-27464093-id-3308003.html
Perl面向对象 Perl面向对象学习例子实例代码教程 - 在我们了解perl的面向对象的概念开始之前,让我们了解引用和匿名数组和哈希表。 在我们了解perl的面向对象的概念开始之前,让我们了解引用和匿名数组和哈希表。 引用 引用是完全像名称所暗示的一样,给另一个对象的引用或指针。 有两种类型的引用:符号和硬引用。 一个符号参考,使您能够引用一个变量的名称,使用另一个变量值。 例如,如果变量$foo的包含字符串“bar”,符号引用$foo的关联变量$bar。 一个硬引用是指在数据结构中包含的实际数据。 创建硬引用 一元反斜线运算符用于创建一个命名的变量或子程序,例如: $foo = 'Bill'; $fooref = $foo; 现在$fooref变量一个硬引用$foo的变量。你可以做同样的与其他变量: $array = @ARGV; $hash = \%ENV; $glob = *STDOUT; 要创建一个子程序: sub foo { print "foo" }; $foosub = &foo; 匿名数组 当你直接创建一个引用到一个数组 - 也就是说,没有形成中间指定数组 - 您正在创建一个匿名数组。 创建一个匿名数组是很容易的: $array = [ 'Bill', 'Ben, 'Mary' ]; 这一行分配一个数组,由封闭的方括号中,而不是正常的括号表示,标量$array。赋值的右侧上的值,使该阵列和左侧包含此阵列的参考。 您可以创建更复杂的结构,通过嵌套数组: @arrayarray = ( 1, 2, [1, 2, 3]); @array数组包含三个元素,一个匿名的三个元素的数组的第三个元素是一个引用。 匿名散列 匿名哈希,你也很容易创建需要使用大括号方括号: $hash = { 'Man' => 'Bill', 'Woman' => 'Mary, 'Dog' => 'Ben' }; 解除引用 解引用一个参考的最直接的方法是在前面加上相应的数据类型的字符(标量使用$,阵列使用@,哈希使用%,子程序用&)是你期待在前面的标量量变量包含的引用。 $array = @ARGV; # Create reference to array $hash = \%ENV; # Create reference to hash $glob = *STDOUT; # Create reference to typeglob $foosub = &foo; # Create reference to subroutine #by www.yiibai.com push (@$array, "From humans"); $$array[0] = 'Hello' $$hash{'Hello'} = 'World'; &$foosub; print $glob "Hello World! "; 对象基础 主要有三种,解释的Perl如何处理对象的角度来看。 该使用条款是对象,类和方法。 在Perl中,对象仅仅是一个参考的数据类型,它知道它属于什么类。对象存储在一个标量变量作为参考。因为一个标量只包含一个对象的引用,同样的标量可以容纳不同的对象,不同的类中。 在Perl中类是一个包,其中包含需要相应的方法来创建和操作对象。 在Perl中一个子程序,程序包定义的方法。该方法的第一个参数是一个对象引用或包名称,取决于该方法是否影响当前对象或类。 Perl提供了bless()函数,用于返回一个引用,并成为一个对象。 定义一个类 定义一个类很简单。在Perl中类是对应于一个包。要创建一个类,我们先建立一个包。包是一个独立的单元,用户定义的变量和子程序,它可以被重新使用一遍又一遍。他们提供了一个单独的命名空间内保持一个Perl程序,子程序和变量以免与其他包中的冲突。 要声明一个类名为Person,我们做: package Person; 包定义的范围延伸到该文件的末尾,或直到遇到另一个package关键字。 创建和使用对象 要创建一个类的实例(对象),我们需要一个对象的构造函数。此构造函数是一个在包中定义的方法。大多数程序员来命名这种新对象的构造方法,但在Perl中,可以使用任何名称。 在Perl中的对象,我们可以使用任何类型的Perl变量。大多数Perl程序员选择使用数组或哈希表的引用。 让我们来创建我们的构造函数使用一个Perl的哈希参考我们的Person类; 当创建一个对象,你需要提供一个构造函数。这是一个子程序,它返回一个对象引用在一个包内。blessing包的类创建的对象引用。例如: package Person; sub new { my $class = shift; my $self = { _firstName => shift, _lastName => shift, _ssn => shift, }; # Print all the values just for clarification. #by www.yiibai.com print "First Name is $self->{_firstName} "; print "Last Name is $self->{_lastName} "; print "SSN is $self->{_ssn} "; bless $self, $class; return $self; } 每类方法通过类名作为第一个参数。 因此,在上面的例子中的类名是“Person”。你可以试试这个打印$class的值。下一步将剩下的参数传递的方法。 $object = new Person( "Mohammad", "Saleem", 23234345); 如果不希望任何类变量分配任何值,可以使用简单的哈希在构造函数。例如 package Person; sub new { my $class = shift; my $self = {}; bless $self, $class; return $self; } 定义方法 其它面向对象语言的概念,如:数据的安全性,以防止程序员等提供直接改变一个对象的数据访问方法来修改对象数据。 Perl没有私有变量,但我们仍然可以使用辅助函数的方法,让程序员不要乱用对象内部结构的概念。 让我们来定义一个辅助方法来获得人的名字: sub getFirstName { return $self->{_firstName}; } 另一种辅助函数来设置人的名字: sub setFirstName { my ( $self, $firstName ) = @_; $self->{_firstName} = $firstName if defined($firstName); return $self->{_firstName}; } 让我们看看到完整的例子:保持Person 包和辅助功能Person.pm文件。 #!/usr/bin/perl package Person; sub new { my $class = shift; my $self = { _firstName => shift, _lastName => shift, _ssn => shift, }; # Print all the values just for clarification. print "First Name is $self->{_firstName} "; print "Last Name is $self->{_lastName} "; print "SSN is $self->{_ssn} "; bless $self, $class; return $self; } sub setFirstName { my ( $self, $firstName ) = @_; $self->{_firstName} = $firstName if defined($firstName); return $self->{_firstName}; } #by www.yiibai.com sub getFirstName { my( $self ) = @_; return $self->{_firstName}; } 1; 现在,在mail.pl文件创建Person对象如下 #!/usr/bin/perl use Person; $object = new Person( "Mohammad", "Saleem", 23234345); # Get first name which is set using constructor. $firstName = $object->getFirstName(); print "Before Setting First Name is : $firstName "; # Now Set first name using helper function. $object->setFirstName( "Mohd." ); # Now get first name set by helper function. $firstName = $object->getFirstName(); print "Before Setting First Name is : $firstName "; This will produce following result First Name is Mohammad Last Name is Saleem SSN is 23234345 Before Setting First Name is : Mohammad Before Setting First Name is : Mohd. 继承 面向对象编程,有时涉及继承。继承仅仅意味着允许一个类被称为“子类“从另一个类继承方法和属性,调用父类, 这样你就不会一遍又一遍写相同的代码。例如,我们可以有一个Employee类继承自Person。 这被称为“是一个”的关系,因为雇员是一个人。Perl有一个特殊的变量@ISA来铺助,@ISA 管理(方法)继承。 以下是使用继承说明 Perl搜索指定对象的指定对象的类。 Perl搜索类中定义的对象类的@ISA阵列。 如果没有在步骤1和2找到方法,那么如果找到一个在@ ISA树,Perl使用AUTOLOAD子程序, 如果仍然无法找到匹配的方法,那么Perl搜索的方法在通用类(包),标准的Perl库的一部分。 如果方法还没有被发现,那么Perl放弃,并提出了一个运行时异常。 因此,要创建一个新的Employee类将继承我们的Person类的方法和属性,我们简单的代码:保持将此程式码放入Employee.pm #!/usr/bin/perl package Employee; use Person; use strict; our @ISA = qw(Person); # inherits from Person Employee类的所有方法和属性继承自Person类,你可以用它如下:使用main.pl文件来测试它 #!/usr/bin/perl use Employee; $object = new Employee( "Mohammad", "Saleem", 23234345); # Get first name which is set using constructor. $firstName = $object->getFirstName(); print "Before Setting First Name is : $firstName "; # Now Set first name using helper function.- by www.yiibai.com $object->setFirstName( "Mohd." ); # Now get first name set by helper function. $firstName = $object->getFirstName(); print "After Setting First Name is : $firstName "; This will produce following result First Name is Mohammad Last Name is Saleem SSN is 23234345 Before Setting First Name is : Mohammad Before Setting First Name is : Mohd. 方法重载 子类Employee继承了所有的方法从父类Person.但是,如果你想在你的子类中重写这些方法,那么你可以实现。在子类中,可以添加额外的函数。它可以做如下:修改Employee.pm文件: #!/usr/bin/perl package Employee; use Person; use strict; our @ISA = qw(Person); # inherits from Person # Override constructor sub new { my ($class) = @_; # Call the constructor of the parent class, Person. my $self = $class->SUPER::new( $_[1], $_[2], $_[3] ); # Add few more attributes $self->{_id} = undef; $self->{_title} = undef; bless $self, $class; return $self; } # Override helper function sub getFirstName { my( $self ) = @_; # This is child class function. print "This is child class helper function "; return $self->{_firstName}; } # Add more methods sub setLastName{ my ( $self, $lastName ) = @_; $self->{_lastName} = $lastName if defined($lastName); return $self->{_lastName}; } sub getLastName { my( $self ) = @_; return $self->{_lastName}; } 1; 现在把下面的代码到main.pl和执行它 #!/usr/bin/perl use Employee; $object = new Employee( "Mohammad", "Saleem", 23234345); # Get first name which is set using constructor. $firstName = $object->getFirstName(); print "Before Setting First Name is : $firstName "; # Now Set first name using helper function. $object->setFirstName( "Mohd." ); # Now get first name set by helper function. $firstName = $object->getFirstName(); print "After Setting First Name is : $firstName "; This will produce following result First Name is Mohammad Last Name is Saleem SSN is 23234345 This is child class helper function Before Setting First Name is : Mohammad This is child class helper function After Setting First Name is : Mohd. 默认自动加载 Perl提供了一个功能,你不会在其他许多编程语言找到:默认的子程序。 如果你定义了一个函数调用AUTOLOAD(),那么任何未定义的子程序的调用将调用AUTOLOAD()函数。在此子程序$ AUTOLOAD缺少的子程序的名称。 这个功能是非常有用的错误处理的目的。下面是一个例子实现的AUTOLOAD,你可以使用自己的方式实现这个函数。 sub AUTOLOAD { my $self = shift; my $type = ref ($self) || croak "$self is not an object"; my $field = $AUTOLOAD; $field =~ s/.*://; unless (exists $self->{$field}) { croak "$field does not exist in object/class $type"; } if (@_) { return $self->($name) = shift; } else { return $self->($name); } } 析构函数和垃圾收集 如果你已经编程使用对象之前,而你将意识到需要创建一个析构函数。当你使用完要释放分配的内存对象。Perl自动为您尽快的对象超出作用域。 如果你想实现你的析构函数关闭文件,或做一些额外的处理,那么你需要定义一个特殊的方法,命名为destroy。 此方法会被调用的对象只是在Perl之前释放分配给它的内存。 在其他方面,就像其他DESTROY方法,可以操作任何你喜欢对象,以便正确地关闭它。 析构函数的方法是简单地一个成员函数(子程序)命名的破坏都会被自动调用 当对象的引用变量超出了作用域。 当对象引用的变量是未定义 当脚本结束 当Perl解释器终止 有关实例: package MyClass; ... sub DESTROY { print " MyClass::DESTROY called "; } 另一种面向对象实例 这里是另一个很好的例子,这将有助于你了解面向对象的概念Perl。把这个源代码转换成任何文件,并执行它。 #!/usr/bin/perl # Following is the implementation of simple Class. package MyClass; sub new { print " MyClass::new called "; my $type = shift; # The package/type name my $self = {}; # Reference to empty hash return bless $self, $type; } sub DESTROY { print " MyClass::DESTROY called "; } sub MyMethod { print " MyClass::MyMethod called! "; } # Following is the implemnetation of Inheritance. package MySubClass; @ISA = qw( MyClass ); sub new { print " MySubClass::new called "; my $type = shift; # The package/type name my $self = MyClass->new; # Reference to empty hash return bless $self, $type; } sub DESTROY { print " MySubClass::DESTROY called "; } sub MyMethod { my $self = shift; $self->SUPER::MyMethod(); print " MySubClass::MyMethod called! "; } # Here is the main program using above classes. package main; print "Invoke MyClass method "; $myObject = MyClass->new(); $myObject->MyMethod(); print "Invoke MySubClass method "; $myObject2 = MySubClass->new(); $myObject2->MyMethod(); print "Create a scoped object "; { my $myObject2 = MyClass->new(); } # Destructor is called automatically here #by www.yiibai.com print "Create and undef an object "; $myObject3 = MyClass->new(); undef $myObject3; print "Fall off the end of the script... "; # Remaining destructors are called automatically here