続・初めてのPerl 第11章 「オブジェクト入門」

練習問題の回答をメモ。

ex11-1
#!/usr/bin/perl
use strict;
use warnings;

{ package Animal;
  sub speak {
    my $class = shift;
    print "a $class goes ", $class->sound, "!\n";
  }
}

{ package Cow;
  use base qw{Animal};
  sub sound { 'moooo' }
}

{ package Horse;
  use base qw{Animal};
  sub sound { 'heheeen' }
}

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

{ package Mouse;
  use base qw{Animal};
  sub sound { 'squeek' }
}

print "Input animal names(Cow Horse Sheep Mouse): ";
chomp(my $usr_input = <STDIN>);

# 初めてのPerl p.150
my @zoo = split /\s+/, $usr_input;
@zoo = map { "\u\L$_" } @zoo; # 各文字の先頭を大文字にする

foreach (@zoo) {
  die "There's no $_ in my zoo!\n" unless /^(Cow|Horse|Sheep|Mouse)$/;
}

foreach my $animal (@zoo) {
  $animal->speak;
}
ex11-2
#!/usr/bin/perl
use strict;
use warnings;

{ package LivingCreature;
  sub speak {
    my $class = shift;
    my $cry = shift;
    if ($cry) {
      print "a $class goes ", $cry, "!\n";
    } else {
      print "a $class goes ", $class->sound, "!\n";
    }
  }
}

{ package Animal;
  use base qw{LivingCreature};
  # Animal にも sound メソッドが必要。無いと、Animal->speak で呼び出したときにエラーになる。これは答え見てから付け足した。
  sub sound { die "All animals can't speak!" }
  sub speak {
    my $class = shift;
    my $cry = shift;
    die "Animal don't cry!" if $cry;
    $class->SUPER::speak;
  }
}

{ package Person;
  use base qw{LivingCreature};
  sub sound { 'hogeeee' }
}

{ package Cow;
  use base qw{Animal};
  sub sound { 'moooo' }
}

{ package Horse;
  use base qw{Animal};
  sub sound { 'heheeen' }
}

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

{ package Mouse;
  use base qw{Animal};
  sub sound { 'squeek' }
}
Mouse->speak;

Person->speak;
Person->speak("piyo piyo");

Animal->speak;

Animalクラスの soundメソッドを定義し忘れていると、実行時のエラーになってしまうから気をつけよう。p.149 のヒントにも書いてあったけど答えを見るまで意味が分からなかったな…。

反省点

共通しそうなコードは上位のクラスにまとめておくと、保守のしやすいプログラムになるよ。今回の例だと、最上位の LivingCreatureクラスが処理の骨格にあたる部分を定義しているね。