1.Perl 面向对象
Perl 中有两种不同地面向对象编程的实现:
一是基于匿名哈希表的方式,每个对象实例的实质就是一个指向匿名哈希表的引用。在这个匿名哈希表中,存储来所有的实例属性。
二是基于数组的方式,在定义一个类的时候,我们将为每一个实例属性创建一个数组,而每一个对象实例的实质就是一个指向这些数组中某一行索引的引用。在这些数组中,存储着所有的实例属性。

2.面向对象基础概念
面向对象有很多基础概念,这里我们接收三个:对象、类和方法。
对象:对象是对类中数据项的引用。.
类:类是个Perl包,其中含提供对象方法的类。
方法:方法是个Perl子程序,类名是其第一个参数。
Perl 提供了 bless() 函数,bless 是用来构造对象的, 通过 bless 把一个引用和这个类名相关联,返回这个引用就构造出一个对象。

3.类的定义
一个类只是一个简单的包。
可以把一个包当作一个类用,并且把包里的函数当作类的方法来用。
Perl 的包提供了独立的命名空间,所以不同包的方法与变量名不会冲突。
Perl 类的文件后缀为 .pm。
接下来我们创建一个 Person 类:
package Person;
类的代码范围到脚本文件的最后一行,或者到下一个 package 关键字前。

4.创建和使用对象
创建一个类的实例 (对象) 我们需要定义一个构造函数,大多数程序使用类名作为构造函数,Perl 中可以使用任何名字。
你可以使用多种 Perl 的变量作为 Perl 的对象。大多数情况下我们会使用引用数组或哈希。
接下来我们为 Person 类创建一个构造函数,使用了 Perl 的哈希引用。
在创建对象时,你需要提供一个构造函数,它是一个子程序,返回对象的引用。
实例如下:
package Person;
sub new
{
my $class = shift;
my $self = {
_firstName => shift,
_lastName => shift,
_ssn => shift,
};
# 输出用户信息
print "名字:$self->{_firstName}\n";
print "姓氏:$self->{_lastName}\n";
print "编号:$self->{_ssn}\n";
bless $self, $class;
return $self;
}
接下来我们创建一个对象:
$object = new Person( "小明", "王", 23234345);

5.定义方法
Perl类的方法只是个Perl子程序而已,也即通常所说的成员函数。
Perl面向对象中Perl的方法定义不提供任何特别语法,但规定方法的第一个参数为对象或其被引用的包。
Perl 没有提供私有变量,但我们可以通过辅助的方式来管理对象数据。
接下来我们定义一个获取名字的方法:
sub getFirstName {
return $self->{_firstName};
}
同样也可以这么写:
sub setFirstName {
my ( $self, $firstName ) = @_;
$self->{_firstName} = $firstName if defined($firstName);
return $self->{_firstName};
}
接下来我们修改 Person.pm 文件的代码,如下所示:
#!/usr/bin/perl
package Person;
sub new
{
my $class = shift;
my $self = {
_firstName => shift,
_lastName => shift,
_ssn => shift,
};
# 输出用户信息
print "名字:$self->{_firstName}\n";
print "姓氏:$self->{_lastName}\n";
print "编号:$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 脚本代码如下:
#!/usr/bin/perl
use Person;
$object = new Person( "小明", "王", 23234345);
# 获取姓名
$firstName = $object->getFirstName();
print "设置前姓名为 : $firstName\n";
# 使用辅助函数设置姓名
$object->setFirstName( "小强" );
# 通过辅助函数获取姓名
$firstName = $object->getFirstName();
print "设置后姓名为 : $firstName\n";

6.继承
Perl里 类方法通过@ISA数组继承,这个数组里面包含其他包(类)的名字,变量的继承必须明确设定。
多继承就是这个@ISA数组包含多个类(包)名字。
通过@ISA只能继承方法,不能继承数据。
接下来我们创建一个 Employee 类继承 Person 类。
Employee.pm 文件代码如下所示:
#!/usr/bin/perl
package Employee;
use Person;
use strict;
our @ISA = qw(Person); # Employee类 继承 Person类
现在 Employee 类包含了 Person 类的所有方法和属性,我们在 main.pl 文件中输入以下代码,并执行:
#!/usr/bin/perl
use Employee;
$object = new Employee( "小明", "王", 23234345);
# 获取姓名
$firstName = $object->getFirstName();
print "设置前姓名为 : $firstName\n";
# 使用辅助函数设置姓名
$object->setFirstName( "小强" );
# 通过辅助函数获取姓名
$firstName = $object->getFirstName();
print "设置后姓名为 : $firstName\n";

7.方法重写
上面实例中,Employee 类继承了 Person 类,但如果 Person 类的方法无法满足需求,就需要对其方法进行重写。
接下来我们在 Employee 类中添加一些新方法,并重写了 Person 类的方法:
#!/usr/bin/perl
package Employee;
use Person;
use strict;
our @ISA = qw(Person); # 从 Person 继承
# 重写构造函数
sub new {
my ($class) = @_;
# 调用父类的构造函数
my $self = $class->SUPER::new( $_[1], $_[2], $_[3] );
# 添加更多属性
$self->{_id} = undef;
$self->{_title} = undef;
bless $self, $class;
return $self;
}
# 重写方法
sub getFirstName {
my( $self ) = @_;
# 这是子类函数
print "这是子类函数\n";
return $self->{_firstName};
}
# 添加方法
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( "小明", "王", 23234345);
# 获取姓名,使用修改后的构造函数
$firstName = $object->getFirstName();
print "设置前姓名为 : $firstName\n";
# 使用辅助函数设置姓名
$object->setFirstName( "小强" );
# 通过辅助函数获取姓名
$firstName = $object->getFirstName();
print "设置后姓名为 : $firstName\n";

8.默认载入
如果在当前类、当前类所有的基类、还有 UNIVERSAL 类中都找不到请求的方法, 这时会再次查找名为 AUTOLOAD() 的一个方法。
如果找到了 AUTOLOAD,那么就会调用,同时设定全局变量 $AUTOLOAD 的值为缺失的方法的全限定名称。
如果还不行,那么 Perl 就宣告失败并出错。
如果你不想继承基类的 AUTOLOAD,很简单,只需要一句:
sub AUTOLOAD;

9.析构函数及垃圾回收
当对象的最后一个引用释放时,对象会自动析构。
如果你想在析构的时候做些什么,那么你可以在类中定义一个名为"DESTROY"的方法。
它将在适合的时机自动调用,并且按照你的意思执行额外的清理动作。
package MyClass;
...
sub DESTROY
{
print "MyClass::DESTROY called\n";
}
Perl 会把对象的引用作为 唯一的参数传递给 DESTROY。
注意这个引用是只读的,也就是说你不能通过访问$_[0] 来修改它。但是对象自身(比如 "${$_[0]" 或者 "@{$_[0]}" 还有 "%{$_[0]}" 等等)还是可写的。
如果你在析构器返回之前重新 bless 了对象引用,那么 Perl 会在析构器返回之后接着调用你重新 bless 的那个对象的 DESTROY 方法。
这可以让你有机会调用基类或者你指定的其它类的析构器。需要说明的是,DESTROY 也可以手工调用,但是通常没有必要这么做。
在当前对象释放后,包含在当前对象中的其它对象会自动释放。

10.Perl 面向对象实例
我们可以通过以下实例来进一步理解Perl面向对象的应用:
#!/usr/bin/perl
# 下面是简单的类实现
package MyClass;
sub new
{
print "MyClass::new called\n";
my $type = shift; # 包名
my $self = {}; # 引用空哈希
return bless $self, $type;
}
sub DESTROY
{
print "MyClass::DESTROY called\n";
}
sub MyMethod
{
print "MyClass::MyMethod called!\n";
}
# 继承实现
package MySubClass;
@ISA = qw( MyClass );
sub new
{
print "MySubClass::new called\n";
my $type = shift; # 包名
my $self = MyClass->new; # 引用空哈希
return bless $self, $type;
}
sub DESTROY
{
print "MySubClass::DESTROY called\n";
}
sub MyMethod
{
my $self = shift;
$self->SUPER::MyMethod();
print " MySubClass::MyMethod called!\n";
}
# 调用以上类的主程序
package main;
print "调用 MyClass 方法\n";
$myObject = MyClass->new();
$myObject->MyMethod();
print "调用 MySubClass 方法\n";
$myObject2 = MySubClass->new();
$myObject2->MyMethod();
print "创建一个作用域对象\n";
{
my $myObject2 = MyClass->new();
}
# 自动调用析构函数
print "创建对象\n";
$myObject3 = MyClass->new();
undef $myObject3;
print "脚本执行结束...\n";
# 自动执行析构函数

23-Perl 面向对象的更多相关文章

  1. Perl面向对象(2):对象

    本系列: Perl面向对象(1):从代码复用开始 Perl面向对象(2):对象 Perl面向对象(3):解构--对象销毁 第3篇依赖于第2篇,第2篇依赖于1篇. 已有的代码结构 现在有父类Animal ...

  2. Perl面向对象(3):解构——对象销毁

    本系列: Perl面向对象(1):从代码复用开始 Perl面向对象(2):对象 Perl面向对象(3):解构--对象销毁 第3篇依赖于第2篇,第2篇依赖于1篇. perl中使用引用计数的方式管理内存, ...

  3. Perl 面向对象编程的两种实现和比较:

    <pre name="code" class="html">https://www.ibm.com/developerworks/cn/linux/ ...

  4. perl面向对象

    来源: http://www.cnblogs.com/itech/archive/2012/08/21/2649580.html Perl面向对象     首先让我们来看看有关 Perl 面向对象编程 ...

  5. Perl面向对象(1):从代码复用开始

    官方手册:http://perldoc.perl.org/perlobj.html 本系列: Perl面向对象(1):从代码复用开始 Perl面向对象(2):对象 Perl面向对象(3):解构--对象 ...

  6. perl 面向对象编程

    今天看到一个perl面向对象编程的例子,充分体现了如何对数据进行封装: 自己模仿写一个读取配置文件的例子, 配置文件的内容如下 samtools_binary = /usr/bin/samtools ...

  7. perl 面向对象 use base

    1.XXX.pm 文件里面的第一行要是:package XXX: 2.要有构造函数 sub new,实现如下: sub new { my $class = shift; # Get the reque ...

  8. 2017.10.23 Java 面向对象深入学习---final 关键字、static关键字、匿名对象等

    今日内容介绍 1.final 关键字 2.static 关键字 3.匿名对象 4.内部类 5.包的声明与访问 6.访问修饰符 7.代码块 第一节课 01(面向对象)final关键字概念.avi 02: ...

  9. perl 面向对象demo

    Vsftp:/root/perl/17# cat Critter.pm package Critter; sub new { my $self = {}; my $invocant = shift; ...

  10. perl 面向对象 new方法

    [root@wx03 test]# cat Scan.pm package Scan; sub new{ my $class = shift; my $self={ 'a'=>11, 'b'=& ...

随机推荐

  1. Leetcode题目236.二叉树的最近公共祖先(中等)

    题目描述: 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q 的祖先 ...

  2. Linux设备驱动程序 之 Makefile

    典型的模块Makefile如下所示: ifneq ($(KERNELRELEASE),) obj-m := hello.o else KERNELDIR ?=/lib/modules/$(shell ...

  3. docker 管理应用程序数据和网络管理

    Volume和Bind Mount Docker提供三种不同方式将数据从宿主机挂载到容器中:volumes,bind mounts和tmpfs volumes:Docker管理宿主机文件系统的一部分( ...

  4. js实现简单的文件上传

    文件下载:https://www.cnblogs.com/xiaomili/p/10521160.html  html: <form name="form1" id=&quo ...

  5. 9Patch图

    NinePatch是一种很有用的PNG图片格式,它可以在特定区域随文字大小进行缩放. - 上边线控制水平拉伸- 左边线控制竖直拉伸- 右边线和下边线控制内容区域 如下: 背景图片的中间区域会随着文字的 ...

  6. VBA ListView控件使用实例

    功能:ListView控件实现连接数据库实现显示查询数据空能. 图片: 代码: Private Sub CommandButton1_Click() Dim res As String res = T ...

  7. SMARTY核心

    http://www.smarty.net/http://smarty.php.net/manual/en/ 1.配置 define("ROOTPATH",dirname(__FI ...

  8. CSS3动画相关属性详解

    本文转载于:<https://blog.csdn.net/lyznice/article/details/54575905> 一.2D效果属性 要使用这些属性,我们需要通过 transfo ...

  9. Linux 查看 MySQL的版本信息

    Linux 查看 MySQL的版本信息 如何查看某台 Linux 主机上的 安装的 MySQL版本信息? 使用如下命令,查看 MySQL的版本信息: mysql -V 或者 mysql --versi ...

  10. StringJoiner,StringBuffer的一些lamada写法

    public String friendlyText(List data) { if(CollectionUtils.isEmpty(data)) { return "[]"; } ...