続・初めてのPerl 第12章 「データのあるオブジェクト」

練習問題の回答をメモ。

#!/usr/bin/perl
use strict;
use warnings;


{ package Animal;
  use Carp;
  sub speak {
    my $class = shift;
    print $class->name, ' goes ',  $class->sound, "!\n";
  }
  sub name {
    my $either = shift;
    ref $either ? $either->{Name} : $either;
  }
  sub set_name {
    my $self = shift;
    ref $self or croak "instance variable needed";
    $self->{Name} = shift;
  }
  sub named {
    ref(my $class = shift) and croak "class name needed";
    my $name = shift;
    my $self = { Name => $name, Color => $class->default_color };
    bless $self, $class;
  }
  sub default_color { 'brown' }
  sub eat {
    my $either = shift;
    my $food = shift;
    print $either->name, " eats $food.\n";
  }
  sub color {
    my $either = shift;
    ref $either ? $either->{Color} : $either->default_color;
  }
  sub set_color {
    my $self = shift;
    ref $self or croak "instance variable needed";
    $self->{Color} = shift;
  }
}

{ package Horse;
  use base qw{Animal};
  sub sound { 'neigh' }
  sub default_color { 'white' }
}

{ package Sheep;
  use base qw{Animal};
  sub sound { 'Meeeee' }
}

my $tv_horse = Horse->named('Mr. ED');
$tv_horse->set_name('Mister Ed');
$tv_horse->set_color('gray');
print $tv_horse->name, ' is ', $tv_horse->color, "\n";
print Sheep->name, ' colored ', Sheep->color, ' goes ', Sheep->sound, "\n";

my $a = Animal->named('BigFatCat');
Animal->set_color('blue');
Animal->set_name('ED');

use Carp を Animal package の中に書かなくちゃいけないのになかなか気づかなくてはまった。解答を見るまで、仮想メソッド(と自分で決めたメソッド)を使うことは思い浮かばなかったな。解答では、&sound と &default_color が仮想メソッドとして扱われていた。

反省点

クラス専用メソッドとインスタンス専用メソッドを ref演算子を使って区別するようにしよう。