[perl] Perl でクラス変数を作る方法

続・初めてのPerl を読んでいて少し混乱したので、クラス変数の作り方をメモしておく。


結論から言うと、Perl でクラス変数を作るには「our演算子」を使う。ラクダ本 p.156 によると、our変数は、

ourは値を生成するのではなく、グローバル変数(これは永遠に存在する)に対して、制限された形でのアクセスを提供するもの

とある。これをラクダ本の言葉を借りて一言で言い直すと、「ourはレキシカルスコープを持つグローバル変数」である。


今のところ、自分の理解している範囲での our は以下のような感じ。
スコープ:レキシカル
命:グローバルなのでメモリ中に1つしか存在しない
ということは、クラス変数としてピッタリだよねっていう話。


以下にクラス変数を作る際の our の使い方を示したサンプルコードを載せておく。

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

{ package Animal;
  use Carp qw(croak);
  use Scalar::Util qw(weaken);

  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};
  }

  # %REGISTRY はクラス変数
  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 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";
  }
}
my $horse = Horse->named('Mr. Ed');
print "We've seen:\n", map "  $_\n", $horse->registered;

参考

続・初めてのPerl p.178:クラス変数の使い方
プログラミングPerl p.155:ourの詳細