我开始使用 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();

PAPB 类中,我都有一个私有(private)变量 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() 声明为私有(private)方法。子类尝试覆盖该方法,但遭到了全面拒绝 - 没有适合您的汤 子类!

现在让我们试试 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 不应该是私有(private)的吗?! MyChild 到底是怎么覆盖 MyParent 中的方法的?!

事实是,MooseX::Privacy 并没有为您提供任何接近大多数 OO 语言中实现的方法隐私的东西。 MooseX::Privacy 类似于在您的方法中执行此操作:
die "GO AWAY!!" unless caller eq __PACKAGE__;

除了 MooseX::Privacy 为您的所有方法调用增加了大量的运行时间。

真的,几乎没有理由使用 MooseX::Privacy。如果您想要私有(private)方法,请将它们放在词法变量中。像这样:
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

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

好的,所以您可以拥有没有 MooseX::Privacy 的私有(private)方法,并且它们比 MooseX::Privacy 更好(更快)。

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

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

关于perl - Perl Moose 类中的私有(private)变量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22972602/

10-15 00:10