tjw*_*992 6 perl accessor moose
使用Perl和Moose
,可以通过两种方式访问对象数据.
$self->{attribute}
要么 $self->attribute()
这是一个简单的例子,展示了两者:
# Person.pm
package Person;
use strict;
use warnings;
use Moose;
has 'name' => (is => 'rw', isa => 'Str');
has 'age' => (is => 'ro', isa => 'Int');
sub HAPPY_BIRTHDAY {
my $self = shift;
$self->{age}++; # Age is accessed through method 1
}
sub HAPPY_BIRTHDAY2 {
my $self = shift;
my $age = $self->age();
$self->age($age + 1); # Age is accessed through method 2 (this will fail)
}
1;
Run Code Online (Sandbox Code Playgroud)
# test.pl
#!/usr/bin/perl
use strict;
use warnings;
use Person;
my $person = Person->new(
name => 'Joe',
age => 23,
);
print $person->age()."\n";
$person->HAPPY_BIRTHDAY();
print $person->age()."\n";
$person->HAPPY_BIRTHDAY2();
print $person->age()."\n";
Run Code Online (Sandbox Code Playgroud)
我知道当你在Person.pm
文件之外时最好使用该$person->age()
版本,因为它可以防止你犯下愚蠢的错误并阻止你覆盖只读值,但我的问题是......
里面的
Person.pm
是它最好使用$self->{age}
或$self->age()
?覆盖模块本身内的只读属性被认为是不好的做法吗?如果该属性预期会发生变化,是否应将此属性更改为读/写属性,或者通过
$self->{age}
在HAPPY_BIRTHDAY
函数内使用来覆盖属性的只读方面是否可接受?
使用Moose时,最佳做法是始终使用生成的访问器方法,即使在对象自己的类中也是如此.原因如下:
访问器方法可能被执行特殊操作的子类覆盖.调用$self->age()
确保将调用正确的方法.
可能存在附加到属性的方法修饰符,例如before
或after
.直接访问哈希值将跳过这些.
可能存在附加到属性的谓词或更清晰的方法(例如has_age
).直接使用哈希值进行混乱会使它们混淆.
哈希键受拼写错误.如果你不小心说$self->{aeg}
错误将不会立即被抓住.但是$self->aeg
因为该方法不存在会死亡.
一致性很好.没有理由在一个地方使用一种风格而在其他地方使用另一种风格.它使代码更易于理解.
在只读属性的特定情况下,以下是一些策略:
使您的对象真正不可变.如果需要更改值,请构造一个新对象,该对象是具有新值的旧对象的克隆.
使用只读属性存储实际年龄,并指定私有编写器方法
例如:
package Person;
use Moose;
has age => ( is => 'ro', isa => 'Int', writer => '_set_age' );
sub HAPPY_BIRTHDAY {
my $self = shift;
$self->_set_age( $self->age + 1 );
}
Run Code Online (Sandbox Code Playgroud)
更新
这是一个如何使用延迟构建器基于另一个设置一个属性的示例.
package Person;
use Moose;
has age => ( is => 'rw', isa => 'Int', lazy => 1, builder => '_build_age' );
has is_baby => ( is => 'rw', isa => 'Bool', required => 1 );
sub _build_age {
my $self = shift;
return $self->is_baby ? 1 : 52
}
Run Code Online (Sandbox Code Playgroud)
懒惰的构建器在age
被访问之前不会被调用,因此您可以确定is_baby
它将存在.
直接设置哈希元素当然会跳过构建器方法.