[ Team LiB ] Previous Section Next Section

9.11 Don't Look Inside the Box

You might have obtained or set the color outside the class simply by following the hash reference: $tv_horse->{Color}. However, this violates the encapsulation of the object by exposing its internal structure. The object is supposed to be a black box, but you've pried off the hinges and looked inside.

One purpose of OOP is to enable the maintainer of Animal or Horse to make reasonably independent changes to the implementation of the methods and still have the exported interface work properly. To see why accessing the hash directly violates this, let's say that Animal no longer uses a simple color name for the color, but instead changes to use a computed RGB triple to store the color (holding it as an arrayref), as in:

use Color::Conversions qw(color_name_to_rgb rgb_to_color_name);
...
sub set_color {
  my $self = shift;
  my $new_color = shift;
  $self->{Color} = color_name_to_rgb($new_color);  # arrayref
}
sub color {
  my $self = shift;
  rgb_to_color_name($self->{Color});               # takes arrayref
}

The old interface can be maintained if you use a setter and getter because they can perform the translations. You can also add new interfaces now to enable the direct setting and getting of the RGB triple:

sub set_color_rgb {
  my $self = shift;
  $self->{Color} = [@_];                # set colors to remaining parameters
}
sub get_color_rgb {
  my $self = shift;
  @{ $self->{Color} };                  # return RGB list
}

If you use code outside the class that looks at $tv_horse->{Color} directly, this change is no longer possible. Store a string ('blue') where an arrayref is needed ([0,0,255]) or use an arrayref as a string.

    [ Team LiB ] Previous Section Next Section