masatoの日記

やっていきます

オブジェクトをつくるのはblessだけじゃない。Class::Accessor::Fastをつかってみた

Perlオブジェクト指向プログラミングをするとき、よくblessを使っていました。で、blessを使ってオブジェクトをつくる場合、コンストラクタやアクセサを自分で書かないといけません。そういうもんだと思ってたところ、これらを自動で処理してくれる便利なモジュールが「モダンPerl入門」に紹介されてました。 自分で試してみたことを以下にメモしてみます。

商品番号、品名、価格からなる行から商品番号を取り出すという単機能モジュールを例にしてやってみました。

blessの場合

パッケージはこんなふう。
まずコンストラクタ。

package Extractor;

sub new {
    my $class = shift;
    my $src = shift;
    my self = bless {
        src => $src,
    }, $class;
    return $self;
}

アクセサは、オブジェクトがもってるプロパティへのインターフェイス
プロパティは、読み書きの両方ができるようにしたいです。 なので、引数の有無によって返り値が変わるようにしてます。 この分岐処理は、上記書籍からコピペさせてもらってます。

sub src {
    my $self = shift;
    my $src = shift;
    my $ret = $self->{$src}; # 引数がなければインスタンス生成のときに入れた値を返す
    if (@_) {
        self->{$src} = @_;
    }
    return $ret;
}

商品番号を返すメソッド。

sub id {
    my $self = shift;
    $self->{src} =~ /^\d+/;
    my $id = $&;
    return $id;
}

実行スクリプト

上記のモジュールを実行してみます。
アイスクリームの商品番号123、カレーライスの商品番号234がそれぞれ取り出せます。

use Extractor;

my $src = '123 ice cream 100 yen';

my $extractor = Extractor->new({ src => $src});
my $product_number = $extractor->id(); 
print $product_number,"\n"; # 123

# srcプロパティを上書きして、商品番号を取り出す
$extractor->{src} = '234 curry rice 800 yen';
$product_number = $extractor->id();
print $product_number,"\n"; # 234

blessのまとめ

コンストラクタ、アクセサを自分で書かないといけない。 プロパティがふえたら、その分アクセサを書く。数が多いと大変。

Class::Accessor::Fastの場合

こちらが本題です。 どうなふうに簡単になるのか。 とても短くなったので、先に上記パッケージ相当のコードをぜんぶ載せます。

package Extractor;
use base qw(Class::Accessor::Fast);

__PACKAGE__->mk_accessors( qw/src/ );

sub id {
    my $self = shift;
    $self->{src} =~ /^\d+/; # 123 ice cream 100 yen -> 123
    my $id = $&;
    return $id;
}

1;

こんだけ。

コンストラクタはモジュールが勝手につくってくれるので、書きません。 アクセサはmk_accessorsというものにプロパティ名を入れるだけです。

__PACKAGE__->mk_accessors( qw/src/ );

これでsrcプロパティの読み書きをやってくれます。 よって、自分で書く必要なし。

実行スクリプトはさっきと同じで同様の値が返ってきます。

まとめ

Class::Accessor::Fastを使うと、オブジェクトを作るときにコンストラクタやアクセサを自分で実装しなくてよいので、機能の実装に集中できそう。
使い方もむずかしくないので、手軽に利用できる。 また、このモジュールは動作が軽いらしいというのもいいと思いました。

モダンPerl入門