13.3. Managing Instance DataProblemEach data attribute of an object, sometimes called data members or properties, needs its own method for access. How do you write these functions to manipulate the object's instance data? SolutionEither write pairs of get and set methods that affect the appropriate key in the object hash, like this: sub get_name { my $self = shift; return $self->{NAME}; } sub set_name { my $self = shift; $self->{NAME} = shift; } Or, make single methods that do both jobs depending on whether they're passed an argument: sub name { my $self = shift; if (@_) { $self->{NAME} = shift } return $self->{NAME}; } Sometimes, it's useful to return the previous value when setting a new value: sub age { my $self = shift; my $prev = $self->{AGE}; if (@_) { $self->{AGE} = shift } return $prev; } # sample call of get and set: happy birthday! $obj->age( 1 + $obj->age ); DiscussionMethods are how you implement the public interface to the object. A proper class doesn't encourage anyone to poke around inside its innards. Each data attribute should have a method to update it, retrieve it, or both. If a user writes code like this:
$him = Person->
then they have violated the interface, so deserve whatever they get. For nominally private data elements, you may omit methods that access them. By mandating a strictly functional interface, you are free to alter your internal representation later without fear of breaking code. The functional interface allows you to run arbitrary range checks and take care of any data reformatting or conversion.
Here's a fancy version of the use Carp; sub name { my $self = shift; return $self->{NAME} unless @_; local $_ = shift; croak "too many arguments" if @_; if ($^W) { /[^\s\w'-]/ && carp "funny characters in name"; /\d/ && carp "numbers in name"; /\S+(\s+\S+)+/ || carp "prefer multiword name"; /\S/ || carp "name is blank"; } s/(\w+)/\u\L$1/g; # enforce capitalization $self->{NAME} = $_; }
If users, even other classes through inheritance, had been accessing the If you're used to C++ objects, then you're accustomed to being able to get at an object's data members as simple variables from within a method. The Alias module from CPAN provides for this, as well as a good bit more, such as the possibility of private methods that the object can call but folks outside the class cannot. Here's an example of creating a Person using the Alias module. When you update these magical instance variables, you automatically update value fields in the hash. Convenient, eh? package Person; # this is the same as before... sub new { my $that = shift; my $class = ref($that) || $that; my $self = { NAME => undef, AGE => undef, PEERS => [], }; bless($self, $class); return $self; } use Alias qw(attr); use vars qw($NAME $AGE @PEERS); sub name { my $self = attr shift; if (@_) { $NAME = shift; } return $NAME; }; sub age { my $self = attr shift; if (@_) { $AGE = shift; } return $AGE; } sub peers { my $self = attr shift; if (@_) { @PEERS = @_; } return @PEERS; } sub exclaim { my $self = attr shift; return sprintf "Hi, I'm %s, age %d, working with %s", $NAME, $AGE, join(", ", @PEERS); } sub happy_birthday { my $self = attr shift; return ++$AGE; }
You need See Alsoperltoot (1), perlobj (1), and perlbot (1); Chapter 5 of Programming Perl ; the documentation for the Alias module from CPAN; Recipe 13.11 ; Recipe 13.12 |
|