由于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.类的函数传入的第一个变量是类名
这点不要忽略掉.如果直接拿参数当成以前那样做法.将会导致参数错位
近期评论