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. CentOS7设置开机启动方式(图形界面/命令行界面)

    CentOS 7由于使用systemd而不是init,所以不能通过修改inittab文件来修改开机启动模式. 先使用ctrl+alt+f2切换到命令行模式,然后输入命令:systemctl set-d ...

  2. 使用PYTHON统计项目代码行数

    目录 一 使用PYTHON统计项目代码行数 二 应用实例 注:原创不易,转载请务必注明原作者和出处,感谢支持! 一 使用PYTHON统计项目代码行数 遇到一个非常小的需求:统计一个项目里头的各类源代码 ...

  3. leetcode 日常清单

    a:excellent几乎一次ac或只有点小bug很快解决:半年后再重刷: b:经过艰难的debug和磕磕绊绊或者看了小提示才刷出来: c:经过艰难的debug没做出来,看答案刷的: 艾宾浩斯遗忘曲线 ...

  4. awk 分组求和

    awk 分组求和 分组求和 awk '{s[substr($2,1,6)] += $1} END{for(i in s) {print i, s[i]/(1024*1024*1024)} }' fil ...

  5. CentOS7 源码安装 PostgreSQL 12

    PostgreSQL 12 源码安装 Table of Contents 1. 下载 2. 准备环境 3. 编译安装 4. 设置环境变量 5. 初始化数据库 6. 配置参数文件 6.1. postgr ...

  6. 注解方式实现AOP编程

    步骤: 1) 先引入aop相关jar文件           (aspectj  aop优秀组件) spring-aop-3.2.5.RELEASE.jar   [spring3.2源码] aopal ...

  7. UI布局属性大全

    第一类:属性值为true或false android:layout_centerHrizontal 水平居中 android:layout_centerVertical 垂直居中 android:la ...

  8. ART模式

    ART模式是Android RunTime的简称,自动对程序进行代码预读取编译,让程序直接编译成机器语言,免去了Dalvik模式要时时转换代码,实现高效率.省电.占用更低的系统内存.手机运行流畅.但凡 ...

  9. C#可以直接调用的Win32API

    以前整理的Win32 API,可以直接在C#中直接调用,在做WinForm时还是很有帮助的.以前用在一个多窗口界面中,当轮询窗口时,调用API会提高很多效率. 源码下载 http://files.cn ...

  10. IPv4 ping命令

    IPv4 ping命令 一.Linux操作系统 给一台 Linux 主机分配了一个 IPv4 的 IP地址,如何使用 ping命令 确定该 IP地址 能否 ping 通呢? 1.查看主机的 IPv4 ...