使用 Moose 的 before 来改变方法参数与隐私冲突
Using Moose's before to alter method arguments clashes with Privacy
作为,我试图在调用其中一种方法时为实例设置属性。我还想将此属性设为私有。正如向我指出的那样,我不能将该属性设置为 ro
,因为这也禁止从 class 中进行读取访问。因此我现在将它设置为 rw
但我已经开始使用 MooseX::Privacy
模块。因此,我的属性声明如下所示:
has 'grow_params' => (
is => 'rw',
isa => 'HashRef',
traits => [qw/Private/],
);
如果我简单地做这样的事情就可以正常工作:
sub grow {
my ($self, $params) = @_;
$self->grow_params($params);
}
不过,我想做一些参数检查。从阅读文档来看,似乎最好的地方是before
。但是,当我尝试这样做时,我 运行 遇到了问题。
例如,before
:
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);
};
这会导致以下错误:
Attribute grow_params is private at C:/strawberry/perl/site/lib/MooseX/Privacy/Meta/Attribute/Private.pm line 13.
(我也试过设置属性为Protected
,猜测可能创建了一个子class,但没有用。)属性确实是私有的,但我正在尝试修改它来自 class 内部,对吗?轨迹看起来像这样,所以我假设 Banana
正在尝试实际设置,还是我遗漏了什么?
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
完整代码给运行你们自己。
# 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([=15=])))[1];
use Banana;
my $chiquita = Banana->new({
peel => 1,
edible => 0,
color => 'green'
});
$chiquita->grow({
size => 'medium',
color => 'yellow'
});
如果我们研究一下
MooseX::Privacy, 更多
具体到
MooseX::Privacy::Meta::Attribute::Private v0.05,
我们可以看到发生了什么。
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 生态系统的内部运作。
作为ro
,因为这也禁止从 class 中进行读取访问。因此我现在将它设置为 rw
但我已经开始使用 MooseX::Privacy
模块。因此,我的属性声明如下所示:
has 'grow_params' => (
is => 'rw',
isa => 'HashRef',
traits => [qw/Private/],
);
如果我简单地做这样的事情就可以正常工作:
sub grow {
my ($self, $params) = @_;
$self->grow_params($params);
}
不过,我想做一些参数检查。从阅读文档来看,似乎最好的地方是before
。但是,当我尝试这样做时,我 运行 遇到了问题。
例如,before
:
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);
};
这会导致以下错误:
Attribute grow_params is private at C:/strawberry/perl/site/lib/MooseX/Privacy/Meta/Attribute/Private.pm line 13.
(我也试过设置属性为Protected
,猜测可能创建了一个子class,但没有用。)属性确实是私有的,但我正在尝试修改它来自 class 内部,对吗?轨迹看起来像这样,所以我假设 Banana
正在尝试实际设置,还是我遗漏了什么?
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
完整代码给运行你们自己。
# 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([=15=])))[1];
use Banana;
my $chiquita = Banana->new({
peel => 1,
edible => 0,
color => 'green'
});
$chiquita->grow({
size => 'medium',
color => 'yellow'
});
如果我们研究一下 MooseX::Privacy, 更多 具体到 MooseX::Privacy::Meta::Attribute::Private v0.05, 我们可以看到发生了什么。
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 生态系统的内部运作。