首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Moose之前修改方法参数与Privacy冲突

使用Moose之前修改方法参数与Privacy冲突
EN

Stack Overflow用户
提问于 2017-07-25 01:18:02
回答 1查看 82关注 0票数 4

作为mentioned earlier today,我尝试在实例的一个方法被调用时设置它的属性。我还希望将此属性设置为私有。正如已经向我指出的,我不能将该属性设置为ro,因为这也会禁止从类内部进行读访问。因此,我现在将其设置为rw,但我已经开始使用MooseX::Privacy模块。因此,我的属性声明如下所示:

代码语言:javascript
运行
复制
has 'grow_params' => (
  is  => 'rw',
  isa => 'HashRef',
  traits => [qw/Private/],
);

如果我简单地执行如下操作,则可以很好地工作:

代码语言:javascript
运行
复制
sub grow {
  my ($self, $params) = @_;
  $self->grow_params($params);
}

但是,我想做一些参数检查。通过阅读文档,似乎最好的地方是before。然而,当我尝试这样做时,我遇到了问题。

例如,使用before

代码语言:javascript
运行
复制
before 'grow_params' => sub {
  my ($self, $params) = @_;
  # Setting default value
  $params->{'overripe'} = exists $params->{'overripe'} ? $params->{'overripe'} : 0;
  # Making sure its boolean
  confess "Argument 'overripe' has to be 0 or 1"
    unless ($params->{'overripe'} == 0 || $params->{'overripe'} == 1);
};

这会导致以下错误:

代码语言:javascript
运行
复制
Attribute grow_params is private at C:/strawberry/perl/site/lib/MooseX/Privacy/Meta/Attribute/Private.pm line 13.

(我还尝试将该属性设置为Protected,猜测可能创建了一个子类,但无济于事。)该属性确实是私有的,但我正在尝试从类中修改它,对吗?跟踪如下所示,所以我假设Banana正在尝试实际的设置,或者我错过了什么?

代码语言:javascript
运行
复制
Attribute grow_params is private at c:/strawberry/perl/site/lib/MooseX/Privacy/Meta/Attribute/Private.pm line 13.
        MooseX::Privacy::Meta::Attribute::Private::_check_private(Moose::Meta::Class::__ANON__::SERIAL::9=HASH(0x3fd4a00), "Class::MOP::Method::Wrapped", "grow_params", "Banana", "Banana") called at c:/strawberry/perl/site/lib/MooseX/Privacy/Meta/Attribute/Privacy.pm line 31
        Banana::grow_params(Banana=HASH(0x25223e8), HASH(0xed97a8)) called at c:/strawberry/perl/site/lib/Class/MOP/Method/Wrapped.pm line 44
        Banana::_wrapped_grow_params(Banana=HASH(0x25223e8), HASH(0xed97a8)) called at c:/strawberry/perl/site/lib/Class/MOP/Method/Wrapped.pm line 95
        Banana::grow_params(Banana=HASH(0x25223e8), HASH(0xed97a8)) called at C:\xampp\htdocs\grinding\banana\/Banana.pm line 31
        Banana::grow(Banana=HASH(0x25223e8), HASH(0xed97a8)) called at run.pl line 16

运行你自己的完整代码。

代码语言:javascript
运行
复制
# Banana.pm
package Banana;

use strict;
use warnings;
use Carp qw( confess );

use Moose;
use MooseX::Privacy;

has ['peel', 'edible'] => (
  is  => 'ro',
  isa => 'Bool',
  required => 1,
);

has 'color' => (
  is  => 'ro',
  isa => 'Str',
  required => 1,
);

has 'grow_params' => (
  is  => 'rw',
  isa => 'HashRef',
  traits => [qw/Private/],
);

sub grow {
  my ($self, $params) = @_;
  $self->grow_params($params);
}

before 'grow_params' => sub {
  my ($self, $params) = @_;
  # Setting default value
  $params->{'overripe'} = exists $params->{'overripe'} ? $params->{'overripe'} : 0;
  # Making sure its boolean
  confess "Argument 'overripe' has to be 0 or 1"
    unless ($params->{'overripe'} == 0 || $params->{'overripe'} == 1);
};

1;

# run.pl
use strict;
use warnings;

use File::Basename qw(fileparse dirname);
use Cwd qw(abs_path);

# Add current directory to @INC
use lib (fileparse(abs_path($0)))[1];

use Banana;

my $chiquita = Banana->new({
  peel => 1,
  edible => 0,
  color => 'green'
});

$chiquita->grow({
  size => 'medium',
  color => 'yellow'
});
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-07-25 03:32:23

如果我们研究一下MooseX::Privacy的实现,更具体地说是MooseX::Privacy::Meta::Attribute::Private v0.05,我们可以看到发生了什么。

代码语言:javascript
运行
复制
sub _check_private {
    my ($meta, $caller, $attr_name, $package_name) = @_;
    confess "Attribute " . $attr_name . " is private"
        unless $caller eq $package_name;
}

所以,问题一定是$caller不等于$package_name。我想,这是用Perl术语表达隐私概念的一种方式。

谁是before方法的调用者?我稍微修改了代码,以便在支票之前打印$caller。这就是罪魁祸首:

Class::MOP::Method::Wrapped

这与方法修饰符的实现方式有关(顾名思义)。

在我看来,你的期望是合理的,这是MooseX::Privacy的缺陷,也是它处理MOP生态系统内部工作方式的缺陷。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45286468

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档