문제

I just started learning Moose, and I've created a very basic class. Here is my code:

Person.pm

package Person;

use Moose;

has fname => (
  is => 'rw',
  isa => 'Str',
  reader => 'getFirstName',
);

has lname => (
  is => 'rw',
  isa => 'Str',
  reader => 'getLastName',
  writer => 'setLastName',
);

sub printName {
  my $self = shift;
  print $self->getFirstName() . " " . $self->getLastName(), "\n";
}

no Moose;
__PACKAGE__->meta->make_immutable;

person.pl

#!/usr/bin/env perl

use strict;
use warnings;
use Person;

my $person = Person->new(fname => 'jef', lname => 'blah',);
print $person->fname, $person->lname, "\n";
$person->setLastName('bleh');
$person->getName();

Where this code dies is line 8. It will print out the first name attribute, but it will whine about lname Can't locate object method "lname" via package "Person" at ./person.pl line 8. Now, if I take out the writer in lname, all is fine, but how does that make sense? I realize I can use the getters that I created, but I'm curious why a writer would then deny me access to the attribute itself? I guess I'm not understanding something...

도움이 되었습니까?

해결책

lname is not "the attribute itself" because fname is also not "the attribute itself". It, too, is a function that returns the attribute. By writing a reader and writer you are choosing what you prefer these subs to be named, that's all.

Calling a sub by the wrong name fails earlier. The old Perl OO way of blessed hashes, and member fields as hash keys lead to survivable runtime errors when attribute names were typed wrong. The idea behind making subs for accessors is to fail early and completely. As a hash can store any string whatsoever, a blessed object can only call a certain set of functions, either defined for the class or inherited.

According to the Manual,

Each attribute has one or more accessor methods. An accessor lets you read and write the value of that attribute for an object.

By default, the accessor method has the same name as the attribute. If you declared your attribute as ro then your accessor will be read-only. If you declared it as rw, you get a read-write accessor. Simple.

Given our Person example above, we now have a single first_name accessor that can read or write a Person object's first_name attribute's value.

If you want, you can also explicitly specify the method names to be used for reading and writing an attribute's value. This is particularly handy when you'd like an attribute to be publicly readable, but only privately settable. [italics mine]

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top