如何在 Perl 模块中创建私有函数?
我正在开发一个小 Perl 模块,由于某种原因,我有一个测试驱动程序脚本,该脚本使用我的新模块调用我认为是私有的函数之一,并且它是成功的。 我很惊讶,所以我开始搜索谷歌,但我找不到任何关于如何在 Perl 模块中创建私有函数的文档...
我看到一个地方说要在“私有”函数的右大括号后添加分号,就像这样:
sub my_private_function {
...
};
我尝试过,但我的驱动程序脚本仍然可以访问我想要私有的函数。
我将编写一个更短的示例,但这就是我想要的:
Module 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;
}
Driver: 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");
Driver 输出:
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 模块中是否可以有私有函数和变量?
谢谢你帮助我学习!
I am working on a little Perl module and for some reason I had the test driver script that was using my new module call one of the functions that I thought would be private, and it was successful. I was surprised, so I started searching google and I couldn't really find any documentation on how to make private functions in Perl modules...
I saw one place that said to put a semicolon after the closing brace of your "private" function, like this:
sub my_private_function {
...
};
I tried that, but my driver script could still access the function I wanted to be private.
I'll make up something that will be a shorter example, but here's what I'm after:
Module 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;
}
Driver: 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");
Driver output:
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!
So I added a semicolon after the last closing brace in the module, but the output is still the same. The only thing I really found was to add this line as the first line to my private_function:
caller eq __PACKAGE__ or die;
But that seems pretty hacky. I don't have a lot of experience writing Perl modules, so maybe I am setting my module up incorrectly? Is it possible to have private functions and variables in perl modules?
Thanks for helping me learn!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
来自
perldoc perltoot
(大约文档的四分之一):因此,我建议您在“私有”方法的开头添加一两个下划线,以帮助阻止使用。
From
perldoc perltoot
(about a quarter way through the document):Therefore, I recommend you put an underscore or two at the beginning of your "private" methods to help dissuade usage.
只有将代码引用存储在词法变量中的“The Kludge”,该范围之外的任何人都看不到:
而且我无法想到一种方法来创建严格的“受保护”字段。
据我所知,就是这样(除了源过滤器......嘘。我没有提到它们......)
编辑:实际上,事实证明我可以可以想出一种非常混乱的方式来保护。 但这可能涉及通过
AUTOLOAD
子传递所有调用。 (!!)There is only "The Kludge" of storing a code reference in a lexical variable, which no one outside that scope can see:
And I can't think of a way to make rigorously "protected" fields.
That's it as far as I know ( besides source filters...shhhh. I didn't mention them.... )
EDIT: Actually, it turns out I can think of a very messy way of doing protected. But it would probably involve passing all calls through the
AUTOLOAD
sub. (!!)这有效:
This works:
只需检查来电者:
Just check caller:
你想做什么? 也许有更好的 Perl 方法来完成您想要完成的任务。
例如,如果您不想让人们在您的对象中乱搞,因为您想强制封装,则可以使用类似 Class::InsideOut。 该模块有一个 Class::InsideOut::About 文档模块来解释这个概念。 还有 Object::InsideOut,Brian Phillips 已经提到过。
What are you trying to do? Maybe there is a better Perl way of doing whatever you are trying to accomplish.
For instance, if you don't want people mucking around in your objects because you want to enforce encapsulation, you can use something like Class::InsideOut. That module has a Class::InsideOut::About documentation module that explains the concept. There is also Object::InsideOut, which Brian Phillips already mentioned.
当您意识到不能仅使用 Data::Dumper 直接转储对象或查看对象内部以查看其数据时,这种 OO 风格在一段时间后开始感觉有点“un-perlish”。 但是,如果您想尝试一下,我建议使用 Object::InsideOut< /a>. 它支持对象的私有数据和方法以及许多其他方便的功能(访问器生成、默认构造函数等)。
This style of OO starts to feel a little "un-perlish" after a while when you realize you can't just use Data::Dumper to dump the object directly or peek inside the object to look at its data. However, if you want to give it a shot, I'd recommend using Object::InsideOut. It supports private data and methods for your objects along with a number of other handy features (accessor generation, default constructor, etc).
我们可以在 perl 私有函数中编写一些内容来检查来自与
caller[0]
相同的 obj 的调用是否给出了 package.json。We can write some thing below in the perl private function to check whehter the call from the same obj as
caller[0]
gives package.如果您使用像 Moose 这样的系统,您可以获得公共/私有区别,如下所示< a href="http://search.cpan.org/perldoc?MooseX::MethodPrivate" rel="nofollow noreferrer">此处。
If you use a system like Moose, you can get a public/private distinction as seen here.
在您的包的文件中:将私有方法定义为 CODE-Ref,即:
In File for your package: Define private methods as CODE-Ref, i.e.: