- Perl基础
- Perl - 首页
- Perl - 简介
- Perl - 环境
- Perl - 语法概述
- Perl - 数据类型
- Perl - 变量
- Perl - 标量
- Perl - 数组
- Perl - 哈希表
- Perl - IF...ELSE
- Perl - 循环
- Perl - 运算符
- Perl - 日期与时间
- Perl - 子程序
- Perl - 引用
- Perl - 格式
- Perl - 文件I/O
- Perl - 目录
- Perl - 错误处理
- Perl - 特殊变量
- Perl - 编码规范
- Perl - 正则表达式
- Perl - 发送邮件
- Perl高级
- Perl - 套接字编程
- Perl - 面向对象
- Perl - 数据库访问
- Perl - CGI编程
- Perl - 包与模块
- Perl - 进程管理
- Perl - 嵌入式文档
- Perl - 函数引用
- Perl有用资源
- Perl - 问答
- Perl - 快速指南
- Perl - 有用资源
- Perl - 讨论
Perl面向对象编程
我们已经学习了Perl中的引用以及Perl匿名数组和哈希表。Perl中的面向对象概念很大程度上基于引用、匿名数组和哈希表。让我们开始学习Perl面向对象编程的基本概念。
对象基础
从Perl如何处理对象的角度出发,解释三个主要术语:对象、类和方法。
在Perl中,**对象**仅仅是对知道自身所属类的某种数据类型的引用。对象存储为标量变量中的引用。因为标量只包含对对象的引用,所以同一个标量可以在不同的类中保存不同的对象。
在Perl中,**类**是一个包含创建和操作对象所需相应方法的包。
在Perl中,**方法**是一个在包内定义的子程序。方法的第一个参数是对象引用或包名,取决于方法是影响当前对象还是类。
Perl提供了一个**bless()**函数,用于返回最终成为对象的引用。
定义类
在Perl中定义类非常简单。在最简单的形式下,类对应于Perl包。要在Perl中创建类,我们首先创建一个包。
包是用户定义变量和子程序的自包含单元,可以反复重用。
Perl包在Perl程序中提供了一个独立的命名空间,使子程序和变量保持独立,避免与其他包中的那些冲突。
要在Perl中声明名为Person的类,我们这样做:
package Person;
包定义的作用域扩展到文件的末尾,或者直到遇到另一个package关键字。
创建和使用对象
要创建一个类的实例(一个对象),我们需要一个对象构造函数。这个构造函数是在包内定义的方法。大多数程序员选择将这个对象构造函数方法命名为new,但在Perl中可以使用任何名称。
你可以在Perl中使用任何类型的Perl变量作为对象。大多数Perl程序员选择数组或哈希表的引用。
让我们使用Perl哈希引用为Person类创建构造函数。创建对象时,需要提供一个构造函数,它是一个包内的子程序,返回一个对象引用。对象引用是通过将对包的类的引用进行bless创建的。例如:
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}\n"; print "Last Name is $self->{_lastName}\n"; print "SSN is $self->{_ssn}\n"; bless $self, $class; return $self; }
现在让我们看看如何创建对象。
$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}\n"; print "Last Name is $self->{_lastName}\n"; print "SSN is $self->{_ssn}\n"; bless $self, $class; return $self; } sub setFirstName { my ( $self, $firstName ) = @_; $self->{_firstName} = $firstName if defined($firstName); return $self->{_firstName}; } sub getFirstName { my( $self ) = @_; return $self->{_firstName}; } 1;
现在让我们在employee.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\n"; # 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\n";
当我们执行上述程序时,它会产生以下结果:
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类。这被称为“isa”关系,因为员工是人。Perl有一个特殊的变量@ISA来辅助此操作。@ISA控制(方法)继承。
使用继承时,需要考虑以下重要事项:
Perl在指定对象的类中搜索给定的方法或属性,即变量。
Perl搜索在对象类的@ISA数组中定义的类。
如果在步骤1或2中找不到方法,则Perl使用AUTOLOAD子程序(如果在@ISA树中找到)。
如果仍然找不到匹配的方法,则Perl会在标准Perl库的一部分UNIVERSAL类(包)中搜索该方法。
如果仍然找不到方法,则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\n"; # 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\n";
当我们执行上述程序时,它会产生以下结果:
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\n"; 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文件中使用Employee对象并执行它。
#!/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\n"; # 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\n";
当我们执行上述程序时,它会产生以下结果:
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方法与任何其他方法一样,您可以在此方法中实现任何您想要的逻辑。
析构函数方法只是一个名为DESTROY的成员函数(子程序),它将在以下情况下自动调用:
- 当对象引用的变量超出作用域时。
- 当对象引用的变量被undef时。
- 当脚本终止时
- 当perl解释器终止时
例如,您可以简单地将以下DESTROY方法放入您的类中:
package MyClass; ... sub DESTROY { print "MyClass::DESTROY called\n"; }
Perl面向对象编程示例
这是一个很好的例子,它将帮助您理解Perl的面向对象概念。将此源代码放入任何Perl文件中并执行它。
#!/usr/bin/perl # Following is the implementation of simple Class. package MyClass; sub new { print "MyClass::new called\n"; my $type = shift; # The package/type name my $self = {}; # Reference to empty hash return bless $self, $type; } sub DESTROY { print "MyClass::DESTROY called\n"; } sub MyMethod { print "MyClass::MyMethod called!\n"; } # Following is the implemnetation of Inheritance. package MySubClass; @ISA = qw( MyClass ); sub new { print "MySubClass::new called\n"; 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\n"; } sub MyMethod { my $self = shift; $self->SUPER::MyMethod(); print " MySubClass::MyMethod called!\n"; } # Here is the main program using above classes. package main; print "Invoke MyClass method\n"; $myObject = MyClass->new(); $myObject->MyMethod(); print "Invoke MySubClass method\n"; $myObject2 = MySubClass->new(); $myObject2->MyMethod(); print "Create a scoped object\n"; { my $myObject2 = MyClass->new(); } # Destructor is called automatically here print "Create and undef an object\n"; $myObject3 = MyClass->new(); undef $myObject3; print "Fall off the end of the script...\n"; # Remaining destructors are called automatically here
当我们执行上述程序时,它会产生以下结果:
Invoke MyClass method MyClass::new called MyClass::MyMethod called! Invoke MySubClass method MySubClass::new called MyClass::new called MyClass::MyMethod called! MySubClass::MyMethod called! Create a scoped object MyClass::new called MyClass::DESTROY called Create and undef an object MyClass::new called MyClass::DESTROY called Fall off the end of the script... MyClass::DESTROY called MySubClass::DESTROY called