Bri*_*anH 32 perl module perl-module private-functions
我正在研究一个小的Perl模块,由于某种原因,我有一个测试驱动程序脚本,它使用我的新模块调用我认为是私有的函数之一,并且它是成功的.我很惊讶,所以我开始搜索谷歌,我真的找不到任何关于如何在Perl模块中创建私有函数的文档...
我看到一个地方说要在你的"私人"功能的右大括号之后加一个分号,如下所示:
sub my_private_function {
...
};
Run Code Online (Sandbox Code Playgroud)
我尝试过,但我的驱动程序脚本仍然可以访问我想要私有的功能.
我会做一些简短的例子,但这就是我所追求的:
模块TestPrivate.pm:
package TestPrivate;
require 5.004;
use strict;
use warnings;
use Carp;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
require Exporter;
@ISA = qw(Exporter AutoLoader);
our @EXPORT_OK = qw( public_function );
our @EXPORT = qw( );
$VERSION = '0.01';
sub new {
my ( $class, %args ) = @_;
my $self = {};
bless( $self, $class );
$self->private_function("THIS SHOULD BE PRIVATE");
$self->{public_variable} = "This is public";
return $self;
}
sub public_function {
my $self = shift;
my $new_text = shift;
$self->{public_variable} = $new_text;
print "Public Variable: $self->{public_variable}\n";
print "Internal Variable: $self->{internal_variable}\n";
}
sub private_function {
my $self = shift;
my $new_text = shift;
$self->{internal_variable} = $new_text;
}
Run Code Online (Sandbox Code Playgroud)
驱动程序:TestPrivateDriver.pl
#!/usr/bin/perl
use strict;
use TestPrivate 'public_function';
my $foo = new TestPrivate();
$foo->public_function("Changed public variable");
$foo->private_function("I changed your private variable");
$foo->public_function("Changed public variable again");
$foo->{internal_variable} = "Yep, I changed your private variable again!";
$foo->public_function("Changed public variable the last time");
Run Code Online (Sandbox Code Playgroud)
驱动输出:
Public Variable: Changed public variable
Internal Variable: THIS SHOULD BE PRIVATE
Public Variable: Changed public variable again
Internal Variable: I changed your private variable
Public Variable: Changed public variable the last time
Internal Variable: Yep, I changed your private variable again!
Run Code Online (Sandbox Code Playgroud)
所以我在模块中的最后一个右大括号之后添加了一个分号,但输出仍然是相同的.我真正找到的唯一一件事就是将这一行添加为private_function的第一行:
caller eq __PACKAGE__ or die;
Run Code Online (Sandbox Code Playgroud)
但这看起来很糟糕.我没有很多编写Perl模块的经验,所以也许我正在设置我的模块错误?是否可以在perl模块中使用私有函数和变量?
谢谢你帮我学习!
jed*_*awk 35
从perldoc perltoot
(大约四分之一的文件):
Perl没有对谁使用哪种方法施加限制.公共与私人的区别是按惯例,而不是语法.(好吧,除非您使用下面"数据成员作为变量"中描述的Alias模块.)有时您会看到以下划线或下划线开头或结尾的方法名称.此标记是一种约定,表示方法仅对该类是私有的,有时对其最近的熟人(其直接子类)是私有的.但Perl本身并没有强制执行这种区分.这取决于程序员的行为.
因此,我建议您在"私人"方法的开头加上一个或两个下划线,以帮助阻止使用.
Axe*_*man 22
只有"The Kludge"将代码引用存储在词法变量中,该范围之外的任何人都看不到:
my $priv_func1 = sub { my $self = shift; say 'func1'; };
sub public_sub {
my $self = shift;
$priv_func1->( $self );
}
Run Code Online (Sandbox Code Playgroud)
而且我想不出一种方法来制造严格的"受保护"字段.
就我所知,这就是它(除了源代码过滤器......嘘.我没有提到它们......)
编辑:事实上,事实证明,我可以想到一个非常混乱的做保护方式.但它可能涉及通过AUTOLOAD
子传递所有呼叫.(!!)
Leo*_*ans 14
这有效:
my $priv_func1 = sub {
my $self = shift; say 'func1';
};
sub public_sub {
my $self = shift;
$self->$priv_func1(@_);
}
Run Code Online (Sandbox Code Playgroud)
只需检查来电者:
package My;
sub new {
return bless { }, shift;
}
sub private_func {
my ($s, %args) = @_;
die "Error: Private method called"
unless (caller)[0]->isa( ref($s) );
warn "OK: Private method called by " . (caller)[0];
}
sub public_func {
my ($s, %args) = @_;
$s->private_func();
}
package main;
my $obj = My->new();
# This will succeed:
$obj->public_func( );
# This will fail:
$obj->private_func( );
Run Code Online (Sandbox Code Playgroud)
你想做什么?也许有更好的Perl方式来做你想要完成的任何事情.
例如,如果您不希望人们因为您想要强制执行封装而在您的对象中乱逛,您可以使用类似Class :: InsideOut的东西.该模块有一个Class :: InsideOut :: About文档模块,解释了这个概念.还有一些Object :: InsideOut,Brian Phillips已经提到过.