Perl Moose类中的私有变量

Håk*_*and 4 perl moose

我开始使用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();
Run Code Online (Sandbox Code Playgroud)

在这两个阶级PAPB我有一个私有变量var.只在PB我上课时使用MooseX::Privacy.这两种方法有什么区别?我为什么要用MooseX::Privacy

tob*_*ink 5

如果您正在寻找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();
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以像这样编译并运行此示例:

$ javac Main.java
$ java Main
Message from MyParent
Run Code Online (Sandbox Code Playgroud)

注意发生了什么.父类(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();
Run Code Online (Sandbox Code Playgroud)

我们可以像这样运行:

$ perl Main.pl
Another message from MyParent
Run Code Online (Sandbox Code Playgroud)

说,WHA?!?!?!message_string应该是私人的吗?!地狱怎么MyChild覆盖了这个方法MyParent?!

事实上,MooseX :: Privacy并没有像大多数OO语言那样为您提供方法隐私.MooseX ::隐私就像在你的方法中这样做:

die "GO AWAY!!" unless caller eq __PACKAGE__;
Run Code Online (Sandbox Code Playgroud)

除了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();
Run Code Online (Sandbox Code Playgroud)

现在运行它:

$ perl Main2.pl
Message from MyParent
Run Code Online (Sandbox Code Playgroud)

哈利路亚!我们有一个真正的私人方法!

好的,所以你可以拥有没有MooseX :: Privacy的私有方法,它们比MooseX :: Privacy更好(也更快).

但私有属性呢?好吧,我在CPAN上有一个小模块可以帮助你:Lexical :: Accessor.这是一个为您创建属性的小工具,具有"由内而外"存储(即属性值不会存储在对象的祝福hashref中),并在词法变量中安装它的访问器(就像私有$get_message方法一样)以上).

无论如何,这是我对MooseX :: Privacy的看法.