浅谈Perl的类、包、模块与面对对象编程
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 = ( , , [, , ]);
@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[] = 'Hello'
$$hash{'Hello'} = 'World';
&$foosub;
print $glob "Hello World!\n";
对象基础
主要有三种,解释的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}\n";
print "Last Name is $self->{_lastName}\n";
print "SSN is $self->{_ssn}\n";
bless $self, $class;
return $self;
}
每类方法通过类名作为第一个参数。 因此,在上面的例子中的类名是“Person”。你可以试试这个打印$class的值。下一步将剩下的参数传递的方法。
$object = new Person( "Mohammad", "Saleem", );
如果不希望任何类变量分配任何值,可以使用简单的哈希在构造函数。例如
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};
}
#by www.yiibai.com
sub getFirstName {
my( $self ) = @_;
return $self->{_firstName};
}
;
现在,在mail.pl文件创建Person对象如下
#!/usr/bin/perl
use Person;
$object = new Person( "Mohammad", "Saleem", );
# 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";
This will produce following result
First Name is Mohammad
Last Name is Saleem
SSN is
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", );
# 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.- 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\n";
This will produce following result
First Name is Mohammad
Last Name is Saleem
SSN is
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( $_[], $_[], $_[] );
# 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};
}
;
现在把下面的代码到main.pl和执行它
#!/usr/bin/perl
use Employee;
$object = new Employee( "Mohammad", "Saleem", );
# 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";
This will produce following result
First Name is Mohammad
Last Name is Saleem
SSN is
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\n";
}
另一种面向对象实例
这里是另一个很好的例子,这将有助于你了解面向对象的概念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
#by www.yiibai.com
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
浅谈Perl的类、包、模块与面对对象编程的更多相关文章
- Python学习6——再谈抽象(面对对象编程)
1.对象魔法 在面对对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法. 使用对象而非全局变量以及函数的原因有多个,而最重要的好处不过以下几点: 多态:可对不同类型的对象 ...
- (C++)浅谈多态基类析构函数声明为虚函数
主要内容: 1.C++类继承中的构造函数和析构函数 2.C++多态性中的静态绑定和动态绑定 3.C++多态性中析构函数声明为虚函数 1.C++类继承中的构造函数和析构函数 在C++的类继承中, 建立对 ...
- 浅谈《think in java》:一 对象导论总结
清单1. 抽象机制,面向对象程序设计方式 java所基于Smalltalk的特性表现一种纯粹的面向对象设计方式: 万物都是对象 程序是对象的集合(容器),他们通过发送消息(发送请求)来告知彼此所要做的 ...
- 60.浅谈nodejs中的Crypto模块
转自:https://www.cnblogs.com/c-and-unity/articles/4552059.html node.js的crypto在0.8版本并没有改版多少,这个模块的主要功能是加 ...
- 浅谈Java工具类CommonUtils的使用
package com.xushouwei.cn; import java.util.HashMap; import java.util.Map; import org.junit.Test; imp ...
- 【JAVA】浅谈java枚举类
一.什么情况下使用枚举类? 有的时候一个类的对象是有限且固定的,这种情况下我们使用枚举类就比较方便? 二.为什么不用静态常量来替代枚举类呢? public static final int SEASO ...
- 浅谈java枚举类
一.什么情况下使用枚举类? 有的时候一个类的对象是有限且固定的,这种情况下我们使用枚举类就比较方便? 二.为什么不用静态常量来替代枚举类呢? public static final int SEASO ...
- 浅谈js的类数组对象arguments
类数组对象:arguments总所周知,js是一门相当灵活的语言.当我们在js中在调用一个函数的时候,我们经常会给这个函数传递一些参数,js把传入到这个函数的全部参数存储在一个叫做arguments的 ...
- 通俗易懂浅谈理解ES6类this不同指向问题
1. class Btn{ //定义的一个类 constructor(id){ // constructor是一个构造函数,是一个默认方法,通过 new 命令创建对象实例时,自动调用该方法.一个类必须 ...
随机推荐
- 常用WEB服务器的特点介绍
经过系统的学习web服务器,现在知道常用的web服务器的优缺点,这对搭建网站架构时选择使用web服务器很有帮助,现在我简单总结一下: 1. Apache:属于重量级web服务器(重量级主要是在软件包的 ...
- PHPUNIT 单元测试
在windows上的安装可以参考其手册 首先下载phpunit.phar文件 1. 为php的二进制可执行文件建立 一个目录,如C:\bin 2. 将C:\bin添加到系统环境变量中, 3. 打开命令 ...
- REST API TESTING
在敏捷开发过程中 每隔两周就是一个sprint,,, 在上个sprint中,任务就是REST API TESTING 因为以前没做过API 测试,不懂,然后经过询问查找 终于知道,需要发送请求,然后获 ...
- Go 学习笔记(一)
随着Go的应用越来越火热,自己也终于开始学习了.平时经常用C,看着Go还是比较亲切的.好了,开始. 今天主要是按照书上的内容自己简单的实践了下最基本的输出,以及网页功能,上代码: package ma ...
- 【DOM】2.闭包
1.什么是闭包? 函数嵌套函数 内部函数可以引用外部函数的参数和变量 参数和变量不会被JS中的垃圾回收机制 所收回 2.闭包有啥好处?应用在哪? ①希望一个变量长期驻扎在内存中 ②避免全局变量的污染 ...
- [LeetCode]LRU Cache有个问题,求大神解答【已解决】
题目: Design and implement a data structure for Least Recently Used (LRU) cache. It should support the ...
- 卸载redhat6.5的yum,安装centos6的yum,配置第三方yum源
**redhat的yum在线更新是收费的,如果没有注册的话不能使用,如果要使用,需将redhat的yum卸载后,重启安装其他yum源,再配置其他源.** 本文包括配置本地源及第三方源.第三方源包括:网 ...
- os7新特性之生成二维码
先导入CoreImage.framework 生成二维码 读取二维码
- 射频识别技术漫谈(2)——国际标准【worldsing 笔记】
如果你只是智能卡的用户,通常可以不必关注国际标准,但作为智能卡的专业开发人员,则至少也要对相关标准有所了解.国际标准一般都是西方人制定的,原版都是英文的,而所谓中文版往往是对原版的直译,许多情况下并未 ...
- ISE和Modelsim联合仿真(转)
相信很多人会遇到过这个问题,不知如何让ISE调用Modelsim进行仿真.我也迷糊了不少时间,查查找找,终于弄明白了,所以有了本文,和大家分享一下.我尽量讲得详细点儿,多多上图. 我的环境:Windo ...