$self-> {attribute}或$self->属性()
这是一个简单的例子,展示了两者:
- # 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;
- # 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";
我知道当你在Person.pm文件之外时,最好使用$person-> age()版本,因为它可以防止你犯下愚蠢的错误并阻止你覆盖只读值,但我的问题是…
Inside of
Person.pm
is it best to use$self->{age}
or$self->age()
? Is it considered bad practice to overwrite a read-only attribute within the module itself?Should this attribute be changed to a read/write attribute if its value is ever expected to change,or is it considered acceptable to override the read-only aspect of the attribute by using
$self->{age}
within theHAPPY_BIRTHDAY
function?
解决方法
>访问器方法可能被执行特殊操作的子类覆盖.调用$self-> age()可确保调用正确的方法.
>可能有附加到属性的方法修饰符,例如之前或之后.直接访问哈希值将跳过这些.
>可能有一个附加到属性的谓词或更清晰的方法(例如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 );
- }
更新
这是一个如何使用延迟构建器基于另一个设置一个属性的示例.
- package Person;
- use Moose;
- has age => ( is => 'rw',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
- }
在访问年龄之前不会调用惰性构建器,因此您可以确定is_baby将存在.
直接设置哈希元素当然会跳过构建器方法.