[ Team LiB ] Previous Section Next Section

9.8 More Interesting Instances

What if an instance needs more data? Most interesting instances are made of many items, each of which can in turn be a reference or another object. The easiest way to store these items is often in a hash. The keys of the hash serve as the names of parts of the object (also called instance or member variables), and the corresponding values are, well, the values.

How do you turn the horse into a hash?[6] Recall that an object is any blessed reference. You can just as easily make it a blessed hash reference as a blessed scalar reference, as long as everything that looks at the reference is changed accordingly.

[6] Other than calling on a butcher, that is.

Let's make a sheep that has a name and a color:

my $lost = bless { Name => "Bo", Color => "white" }, Sheep;

$lost->{Name} has Bo, and $lost->{Color} has white. But you want to make $lost->name access the name, and that's now messed up because it's expecting a scalar reference. Not to worry, because it's pretty easy to fix up:

## in Animal
sub name {
  my $either = shift;
  ref $either
    ? $either->{Name}
    : "an unnamed $either";
}

named still builds a scalar sheep, so let's fix that as well:

## in Animal
sub named {
  my $class = shift;
  my $name = shift;
  my $self = { Name => $name, Color => $class->default_color };
  bless $self, $class;
}

What's this default_color? If named has only the name, you still need to set a color, so you'll have a class-specific initial color. For a sheep, you might define it as white:

## in Sheep
sub default_color { "white" }

Then to keep from having to define one for each additional class, define a backstop method, which serves as the "default default," directly in Animal:

## in Animal
sub default_color { "brown" }

Thus, all animals are brown (muddy, perhaps), unless a specific animal class gives a specific override to this method.

Now, because name and named were the only methods that referenced the structure of the object, the remaining methods can stay the same, so speak still works as before. This supports another basic rule of OOP: if the structure of the object is accessed only by the object's own methods or inherited methods, there's less code to change when it's time to modify that structure.

    [ Team LiB ] Previous Section Next Section