[ Team LiB ] Previous Section Next Section

9.10 Getting Your Deposit Back

Because of the way the code is written, the setter also returns the updated value. Think about this (and document it) when you write a setter. What does the setter return? Here are some common variations:

  • The updated parameter (same as what was passed in)

  • The previous value (similar to the way umask or the single-argument form of select works)

  • The object itself

  • A success/fail code

Each has advantages and disadvantages. For example, if you return the updated parameter, you can use it again for another object:

$tv_horse->set_color( $eating->set_color( color_from_user(  ) ));

The implementation given earlier returns the newly updated value. Frequently, this is the easiest code to write, and often the fastest to execute.

If you return the previous parameter, you can easily create "set this value temporarily to that" functions:

{
  my $old_color = $tv_horse->set_color("orange");
  ... do things with $tv_horse ...
  $tv_horse->set_color($old_color);
}

This is implemented as:

sub set_color {
  my $self = shift;
  my $old = $self->{Color};
  $self->{Color} = shift;
  $old;
}

For more efficiency, you can avoid stashing the previous value when in a void context using the wantarray function:

sub set_color {
  my $self = shift;
  if (defined wantarray) {
    # this method call is not in void context, so
    # the return value matters
    my $old = $self->{Color};
    $self->{Color} = shift;
    $old;
  } else {
    # this method call is in void context
    $self->{Color} = shift;
  }
}

If you return the object itself, you can chain settings:

my $tv_horse =
  Horse->named("Mr. Ed")
       ->set_color("grey")
       ->set_age(4)
       ->set_height("17 hands");

This works because the output of each setter is the original object, becoming the object for the next method call. Implementing this is again relatively easy:

sub set_color {
  my $self = shift;
  $self->{Color} = shift;
  $self;
}

The void context trick can be used here too, although with questionable value because you've already established $self.

Finally, returning a success status is useful if it's fairly common for an update to fail, rather than an exceptional event. The other variations would have to indicate failure by throwing an exception with die.

In summary: use what you want, be consistent if you can, but document it nonetheless (and don't change it after you've already released one version).

    [ Team LiB ] Previous Section Next Section