perl不像C++、java,在类中可以直接通过private来声明成员私有。
对于成员变量,如果我们在类中直接声明,那么,perl会认为这是一个类变量,即相当于C++里面的static成员变量,该变量被所有类共享,要声明私有,只有通过闭包(closure)的方法。
以下先简单介绍闭包(closure)。
我们可以将闭包理解为一个匿名子程序,其作用就是将其内部的变量封装起来,外部只有通过这个匿名子程序的引用才能访问该变量,闭包声明时,提供了一种方法可以在定义子程序的时候向子程序传递值,也就是初始化子程序。
example:
sub getref_closure{
my $str1;
if (@_){
$str1 = shift;
}
else{
$str1 = "hello";
}
return {
my $str2 = shift;
print "$str1 $str2/n";
}
}
例子调用getref_closure来初始化$str1,下一步在子程序中将用户指定字符串或默认字符串Hell存入$str1中,并将返回的匿名子程序到外部引用变量中。
对于类的私有成员变量,我们可以在构造函数中声明一变量,在匿名子程序中使用,并返回给以引用,通过bless方法绑定该引用再返回给用户。
程序例子如下:
sub new{
print shift,"/n";
my $data = {};
$$data{'name'} = "xiaoming";
my $closure = sub {
shift;
if (@_){
$$data{'name'} = shift;
}
else{
return $$data{'name'};
}
};
bless($closure);
return $closure;
}
用户通过类的new方法得到一个匿名子程序的引用,也是这个类的对象,此时这个对象里面有一个私有成员变量$$data{'name'},但是用户不能通过$object->data{'name'}来获得,因为$$data{'name'}的作用域限定在new方法和匿名子程序内部。
要访问内部变量,我们有两种方法,一种是直接调用对象方法&{$object}("tttttttttttt"),这样,tttttttt就会传给匿名函数的内部变量。第二种方法是在类中封装一个函数去访问这个匿名函数,如下:
sub name(){
print "object = $_[0]/n";
&{$_[0]};
}
通过返回的对象访问:
$object->name("fff");
下面说说私有成员函数,如果函数直接在类中定义,那么如C++的公有成员函数,可以给用户直接访问。要屏蔽用户的访问权限,可以在类中定义一个匿名函数,传给类中的一个引用变量,在类中其他子程序可通过这个函数引用调此函数,这样,对于外部使用用户来说,此函数是透明的,对于类里面来说,这个函数可以被类中的其他函数所访问。例子如下:
my $ref_hello = sub {
print "hello world!/n";
};
此时,类中的其他方法可通过解引用访问私有成员函数:&$ref_hello();