我开始使用Moose了解Perl中的对象.
我不确定我是否理解MooseX :: Privacy的目的.考虑:
use v5.14; package PA { use Moose; my $var='private?'; 1; sub getVar { return $var; } } package PB { use Moose; use MooseX::Privacy; has 'var' => ( is => 'rw',isa => 'Str',default => 'private?',traits => [qw/Private/],); 1; sub getVar { my $self = shift; return $self->var; } } my $o1= PA->new(); my $o2= PB->new(); say $o1->getVar(); say $o2->getVar();
在PA和PB类中,我有一个私有变量var.仅在PB类中我使用MooseX :: Privacy.这两种方法有什么区别?我为什么要使用MooseX :: Privacy?
解决方法
如果您正在寻找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并没有像大多数面向对象语言那样为您提供方法隐私. MooseX ::隐私就像在你的方法中这样做:
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中),并在词法变量中安装它的访问器(就像上面的私有$get_message方法一样).
无论如何,这是我对MooseX :: Privacy的看法.