続・初めてのPerl 第13章 「オブジェクトのデストラクション」
練習問題の回答をメモ。
#!/usr/bin/perl use strict; use warnings; { package Animal; use Scalar::Util qw(weaken); use Carp qw(croak); sub speak { my $class = shift; print $class->name, ' goes ', $class->sound, "!\n"; } sub name { my $either = shift; ref $either or croak "instance variable needed"; $either->{Name}; } our %REGISTRY; sub named { ref(my $class = shift) and croak 'class only'; my $name = shift; my $self = { Name => $name, Color => $class->default_color }; bless $self, $class; $REGISTRY{$self} = $self; weaken($REGISTRY{$self}); $self; } sub registered { return map { 'a ' . ref($_) . " named " . $_->name } values %REGISTRY; } sub default_color { 'brown' } sub eat { my $either = shift; my $food = shift; print $either->name, " eats $food.\n"; } sub color { my $self = shift; $self->{Color}; } sub set_color { my $self = shift; $self->{Color} = shift; } sub DESTROY { my $self = shift; print '[', $self->name, " has died.]\n"; } } { package Horse; use base qw{Animal}; sub sound { 'neigh' } sub default_color { 'white' } sub DESTROY { my $self = shift; $self->SUPER::DESTROY; print "[", $self->name, " has gone off to the glue factory.]\n"; } } { package RaceHorse; use base qw{Horse}; my %DATA; sub named { my $self = shift->SUPER::named(@_); dbmopen(%DATA, "horse_db", 0644) or die "Cannot create horse_db: $!"; my $db_data = $DATA{ref($self)}; if (defined($db_data)) { @$self{ qw/wins places shows losses/ } = split / /, $db_data; } else { $self->{$_} = 0 for qw(wins places shows losses); } $self; } sub won { shift->{wins}++ } sub placed { shift->{places}++ } sub showed { shift->{shows}++ } sub lost { shift->{losses}++ } sub standings { my $self = shift; join ', ', map "$self->{$_} $_", qw(wins places shows losses); } sub DESTROY { my $self = shift; $self->SUPER::DESTROY; $DATA{ref($self)} = join ' ', map "$self->{$_}", qw(wins places shows losses); } } my $runner = RaceHorse->named('Billy Boy'); $runner->won; print $runner->name, ' has standings ', $runner->standings, ".\n";
反省点
ハッシュリファレンスのスライスではまったよ(70行目)。
正しいハッシュリファレンスのスライス
@$self{ qw/wins places shows losses/ } = split / /, $db_data;
ハッシュリファレンスのスライス?これは間違い
@$self->{ qw/wins places shows losses/ } = split / /, $db_data;
前のエントリにまとめておいたよ。
Perl のハッシュリファレンスのスライスの書き方 - 英語とプログラミング気まぐれ日記