我正在开发一个小Perl模块,由于某种原因,我让测试驱动脚本使用我的新模块调用了一个我认为是私有的函数,它成功了。我很惊讶,所以我开始搜索谷歌,我真的找不到任何关于如何在Perl模块中创建私有函数的文档...
我看到有一个地方说要在“private”函数的右大括号后面放一个分号,就像这样:
sub my_private_function {
...
};
我试过了,但是我的驱动程序脚本仍然可以访问我想要的私有函数。
我会编一个更短的例子,但下面是我的目标:
模块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;
}
驱动程序: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");
驱动程序输出:
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!
所以我在模块的最后一个右大括号后面添加了一个分号,但是输出仍然是一样的,我唯一真正找到的是将下面这行作为第一行添加到我的private_function中:
caller eq __PACKAGE__ or die;
但是这看起来很笨拙。我没有很多编写Perl模块的经验,所以也许我的模块设置不正确?在Perl模块中有没有可能有私有函数和变量?
谢谢你帮我学习!
9条答案
按热度按时间798qvoo81#
从
perldoc perltoot
开始(大约文档的四分之一):Perl并不限制谁可以使用哪种方法,public与private的区别是根据惯例而不是语法。(好吧,除非您使用“作为变量的数据成员”中介绍的Alias模块。)有时您会看到方法名以一条或两条下划线开头或结尾。这种标记是一种约定,表示方法只对该类私有,有时也对它最亲近的人私有,它的直接子类。但是Perl本身并不强制执行这种区分。这取决于程序员的行为。
因此,我建议您在“private”方法的开头加上一两个下划线,以避免使用。
r3i60tvu2#
只有在词法变量中存储代码引用的“Kludge”,该作用域之外的任何人都看不到:
我也想不出一种方法来严格地“保护”字段。
据我所知就是这样(除了源过滤器...嘘。我没有提到它们...)
**编辑:**事实上,我 * 能 * 想到一种非常混乱的保护方式。但它可能涉及通过
AUTOLOAD
sub传递所有调用。(!!)tmb3ates3#
这是可行的:
t1qtbnec4#
刚查来电人:
zhte4eai5#
你想做什么?也许有一个更好的Perl方法来做你想完成的事情。
例如,如果你不想让人因为你想强制封装而在你的对象中捣乱,你可以使用类似Class::InsideOut的东西。这个模块有一个Class::InsideOut::About文档模块来解释这个概念。还有一个Object::InsideOut,Brian菲利普斯已经提到过。
qfe3c7zg6#
当您意识到不能直接使用Data::Dumper转储对象或查看对象内部的数据时,这种OO风格开始有点“不完美”。但是,如果您想给予一下,我建议使用Object::InsideOut。它支持对象的私有数据和方法沿着许多其他方便的特性(访问器生成、默认构造函数等)。
xdnvmnnf7#
我们可以在下面的perl私有函数中写一些东西来检查来自
caller[0]
的同一个对象的调用是否给出包。gcxthw6b8#
如果您使用Moose这样的系统,您可以获得如here所示的public/private区别。
6ju8rftf9#
在软件包的文件中:将私有方法定义为CODE-Ref,即: