Perl面向对象编程初探-1
由于Perl的面向对象编程是后来加入的. 所以其语法以及其他元素都显得比较不自然. 下面是这两天来对于Perl的O...
扫描右侧二维码阅读全文
04
2009/02

Perl面向对象编程初探-1

由于Perl的面向对象编程是后来加入的.
所以其语法以及其他元素都显得比较不自然.
下面是这两天来对于Perl的OO编程的初步的一些探索
首先是类的建立
Perl的原则是不引入过多的保留字
所以Perl的类没有引入新的例如class之类的关键词,
而是使用了原来的包的概念.也就是一个类就是一个包.
包之内的函数就是类的function,包之类经过bless的数据结构,就是类的数据结构以及类本身
我们先来看一个例子

#!/usr/bin/perl -w package Person; #使用包来创建Person类 $data = {}; #在包内创建包变量(全局变量) #类的函数,初始函数可以是任意名称,不是一定需要用new #但是new一般是约定俗成的名字 sub new() { my ( $class, @args ) = @_; #注意,类的所有函数的参数都会传入一个隐含参数 #隐含参数是第一个参数,其值就是类的名称,这里就是Person my ( $name, $age ) = @args; ( $data->{name}, $data->{age} ) = @args; #我们将后续的参数放入类的数据中,对类进行初始化 bless $data, $class; #这一步是Perl和所有其他语言的不同之处 #bless的含义是将变量上绑定类信息,这样对于这个数据就可以 #调用类的函数 return $data; #将帮定了类信息的数据结构返回,这样其他程序就可以通过new #函数的调用之后的返回值来调用Person类里面的函数 } sub printname() { print $data->{name} . "\n"; } package main; #切换到主包 $pack = Person->new( "code_tin", 29 ); #创建一个Person类的对象,并且用参数进行初始化 #这里再提示一次,所有类的函数的调用.其第一个传入的参数都是 #隐含的类的名称,这点在后面分析其他创建类的方法中很有用 #除了上面所用的方法外,创建类还有2种方式 # $pack = Person::new( "code_tin", 29 ); 以及 # $pack = new Person( "code_tin", 29 ); $pack->printname(); #结果将是输出code_tin

这个例子和外面的很多Perl OO教程内的例子不一样.
而这个例子比外面的要简单.外面的很多例子太过于拘泥语法,有些太过于矫情
下面就是一般外面的OO所用的方法.在注释中我会标出区别

#!/usr/bin/perl -w package Person; sub new() { my $data = {}; #将类的数据结构放在初始化函数中,作为局部变量,增加了安全性 my ( $class, @args ) = @_; my ( $name, $age ) = @args; bless $data, $class; ( $data->{name}, $data->{age} ) = @args; return $data; } sub printname() { my ($localdata)=@_; #这里多了一个创建局部变量,由于前面$data位于new()中 #所以这里访问利用到了隐含参数,将类的引用重新复制一份在此函数中使用 #类中的其他函数也需要作这一步. print $localdata->{name} . "\n"; } package main; $pack = Person->new( "code_tin", 29 ); $pack->printname();


这里有几个区别的地方
1.数据结构放入了new函数内.这样增强了访问控制
有人前面可能就有疑问.将$data作为全局变量会不会别的类也用到
这里要提的是全局变量也就是包变量,他虽然在全局可视,但是别的包要
使用$data,则会默认是其本身包的$data,而不会是这个.
在其他包中要调用这个$data,需要指定包名称$Person::data
所以我还是推荐前面一种方法
2.由于类的数据放在了new函数内,
导致每个类的函数中都需要创建一个局部变量来指向这个数据结构
比较麻烦,个人觉得没有为了所谓的访问控制来作这种操作.
因为Perl的OO的理念本来就不是强访问控制的.
还有几个值得注意的地方
1.在package中不要以为使用my变量就是作用范围在包中,
my变量确实作用范围在代码块中,但是如果你在package后面跟着my变量
那么这个变量的作用域将会是全局.
因为package不是代码块
而大括号之间的内容才属于一个代码块
所以在package后面的my变量将不是由你所希望的那样变成package的私有变量
2.构建函数最后要return经过bless的变量.
在上面代码中如果你把new函数中最后的return删除
你会发现代码依然工作正常
因为Perl的特性就是会默认return最后操作的变量回去
而new里面一般可能最后是一个bless操作.而正好就把bless之后的内容返回回去了
但是如果你在new函数最后一句是操作的其他参数
你就会发现去掉return之后
在main::里面调用Person的函数会报错说找不到Person::函数名这个东西.
因为你没有把包含类信息的东西返回回去.
3.类的函数传入的第一个变量是类名
这点不要忽略掉.如果直接拿参数当成以前那样做法.将会导致参数错位

Last modification:November 26th, 2018 at 04:16 pm
If you think my article is useful to you, please feel free to appreciate

2 comments

  1. aXqd

    <Perl Best Practises>

  2. aXqd

    use Class::Std;
    {
    # standard "inside-out" class
    }

    from

Leave a Comment