如果您正在寻找 Java 风格的方法隐私,那么 MooseX::Privacy 将会非常令人失望。以下是 Java 风格的方法隐私会发生的情况:
/* This file is called Main.java */
public class Main
{
public class MyParent
{
private String message_string ()
{
return "Message from %s\n";
}
public void print_message ()
{
System.out.printf( this.message_string(), "MyParent" );
}
}
public class MyChild extends MyParent
{
public String message_string ()
{
return "Another message from %s\n";
}
}
public static void main (String[] args)
{
Main o = new Main();
o.run();
}
public void run ()
{
MyParent c = new MyChild();
c.print_message();
}
}
你可以像这样编译和运行这个例子:
$ javac Main.java
$ java Main
Message from MyParent
注意发生了什么。父类 (MyParent) 将 message_string() 声明为私有方法。子类尝试重写该方法,但遭到彻底拒绝 - 没有给你的汤子类!
现在让我们试试 Perl 和 MooseX::Privacy 的等价物...
# This file is called Main.pl
use v5.14;
use strict;
use warnings;
package MyParent {
use Moose;
use MooseX::Privacy;
private_method message_string => sub {
my $self = shift;
return "Message from %s\n";
};
sub print_message {
my $self = shift;
printf($self->message_string(), __PACKAGE__);
}
}
package MyChild {
use Moose; extends qw(MyParent);
use MooseX::Privacy;
sub message_string {
my $self = shift;
return "Another message from %s\n";
}
}
my $c = new MyChild();
$c->print_message();
我们可以这样运行:
$ perl Main.pl
Another message from MyParent
说,WHA?!?!?!message_string 不应该是私人的吗?! MyChild到底是怎么覆盖MyParent中的方法的?!
事实上,MooseX::Privacy 并没有像在大多数 OO 语言中实现的那样为您提供接近方法隐私的任何东西。 MooseX::Privacy 类似于在您的方法中执行此操作:
die "GO AWAY!!" unless caller eq __PACKAGE__;
除了 MooseX::Privacy 会为您的所有方法调用增加大量运行时开销。
真的,没有理由使用 MooseX::Privacy。如果您想要私有方法,请将它们放在词法变量中。像这样:
use v5.14;
use strict;
use warnings;
package MyParent {
use Moose;
my $message_string = sub {
my $self = shift;
return "Message from %s\n";
};
sub print_message {
my $self = shift;
printf($self->$message_string(), __PACKAGE__);
}
}
package MyChild {
use Moose; extends qw(MyParent);
sub message_string {
my $self = shift;
return "Another message from %s\n";
}
}
my $c = new MyChild();
$c->print_message();
现在运行它:
$ perl Main2.pl
Message from MyParent
哈利路亚!!我们有一个真正的私有方法!
好的,因此您可以在没有 MooseX::Privacy 的情况下使用私有方法,并且它们比 MooseX::Privacy 工作得更好(更快)。
但是私有属性呢?好吧,我有一个关于 CPAN 的小模块可以帮助你:Lexical::Accessor。这是一个为您创建属性的小工具,具有“由内而外”存储(即属性值不会存储在对象的祝福 hashref 中),并将访问器安装在词法变量中(就像私有 @ 987654334@上面的方法)。
无论如何,这就是我对 MooseX::Privacy 的看法。