アクセサ(4) Class::Accessor

CPANからのインストールも済んだので、Class::Accessorの使い方を勉強します。
といっても、使い方はとっても簡単です。Class::Accessor を継承すれば mk_accessors というクラスメソッドが使えるようになります。このメソッドに「属性名のリスト」を渡せば、自動的にその属性に対するアクセサ(getter/setter)を作ってくれます。
Class::Structの時に書いたコード を Class::Accessor を使って書き換えてみます。

package Person;
use strict;
use base qw(Class::Accessor);
Person->mk_accessors(qw(name age));
 
sub introduce {
    my $self = shift;
    print "I am " . $self->name();
    print ", " . $self->age() . " years old.\n";
}
 
package main;
use strict;
my $man = Person->new({name => "Somebody", age => 0});
$man->introduce();
 
$man->name("Taro");
$man->age(10);
$man->introduce();

ひとつずつ解説します。

use base qw(Class::Accessor);

base モジュールを使って Class::Accessor を継承しています。base モジュールは use する時に渡したモジュール名のリストを順番に require してから、リストを @ISA にセットしてくれます。多重継承もサポートしています。

Person->mk_accessors(qw(name age));

mk_accessors クラスメソッドを呼び出して、アクセサを生成しています。
qw は囲んだ文字列を空白で区切ったリストを返してくれる演算子でしたね。つまり、この場合 "name" と "age" という2つのアクセサメソッドが生成される事になります。

sub introduce {
    my $self = shift;
    print "I am " . $self->name();
    print ", " . $self->age() . " years old.\n";
}

アクセサで値を取得して表示しています。アクセサに何も渡さずに呼び出すと、値が取得できます。
文字列を連結する時は「.」(ドット)を使います。「+」(プラス)は数値の足し算を行なう演算子なので間違えないようにしましょう。他の言語だと「+」が文字列の連結演算子を兼ねている事が多いので気をつけなくては。

my $man = Person->new({name => "Somebody", age => 0});
$man->introduce();

コンストラクタ new は、Class::Accessor に宣言されているので継承できます。ハッシュのリファレンスを渡すと、各アクセサの初期値を決められます。

$man->name("Taro");
$man->age(10);
$man->introduce();

アクセサに値を渡して、値を設定しています。

実行結果は以下の通りです。

I am Somebody, 0 years old.
I am Taro, 10 years old.

ちゃんとアクセサが動作していますね。

ちなみに、「mk_ro_accessors」メソッドで「読み取り専用のアクセサメソッド」が、「mk_wo_accessors」メソッドで「書き込み専用のアクセサメソッド(ミューテータ)」が生成できます。

Class::Accessor によって生成されたアクセサメソッドを通じてオブジェクトの属性を取得/設定しようとすると、そのオブジェクトの get メソッド / set メソッドが経由されます。
これらのメソッドをオーバーライドする事で、アクセサメソッドの挙動を細かく制御できます。

Class::Accessor::Fast というモジュールもあります。こちらは基本的に Class::Accessor と同じ機能を持っているのですが、値の取得/設定の際に get/set メソッドを経由しないので Class::Accessor に比べて速く動作します。
上のコードのように、アクセサの挙動を特に変更しない場合は、Class::Accessor::Fast を使ったほうがいいですね。

アクセサの勉強はとりあえずこの辺りで終わりにします。まだまだ勉強しなくちゃいけない事が山積みですので。(^_^)