SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Webアプリケーションフレームワーク「Catalyst」入門

初めてのCatalyst入門(6)
Perlのオブジェクト指向とモデル

blessとMooseの違い、Catalystのモデルについて解説


Mooseを使用した例

 次にMooseを使用してPersonBaseballPlayerを定義する例を見ていきましょう。Mooseではblessをそのまま使用する場合に比較して、プロパティやメソッドのオーバーライドなどが簡単に定義できるようになっています。

[リスト5]Moose版Personクラス
package moosified::Person;
# (1)Mooseを読み込む
use Moose;
# (2)プロパティの定義
has 'name' => (
  is  => 'rw',
  isa => 'Str',
  default => 'none',
);
has 'age' => (
  is  => 'ro',
  isa => 'Int',
  default => 0,
);
sub introduce {
  my $self = shift;
  print 'My name is ' , $self->name() , ', ' , $self->age() , " years old.\n";
}
# (3)Mooseの関数を名前空間から削除し、クラスを不変化する
no Moose;
__PACKAGE__->meta->make_immutable;

1;

 blessを使用した定義に比べると、newメソッドがない、プロパティ定義らしき部分に「has 'name' => (...)」と記述されている、などの違いが見て取れると思います。

 Mooseを使用するには(1)のように「use Moose」でMooseを読み込みます。このときにuse strictuse warningsも同時に設定されます。またMooseで定義されているhasなどの関数も併せて読み込まれます。Mooseでのプロパティ定義は(2)のようにhas関数を使用して行います。hasで使用可能な主要オプションには次のようなものがあります。

 その他のオプションについてはMoose#EXPORTED_FUNCTIONSの項目を参照ください。

hasで使用可能なオプション(一部)
名前 指定可能な値 説明
is roまたはrw プロパティへのアクセスが読み込み専用か読み書き可能かを設定する
isa データ型 プロパティへのデータ型を設定する
default スカラ値またはコード デフォルト値を設定する。スカラ値だけではなくデフォルト値を生成するコードも指定可能
required 0または1 newメソッドで必須の場合には1を、そうでない場合には0を設定する
trigger コードへの参照 プロパティへ値が設定された場合に、指定したコードが実行される
clearer クリア用メソッド名 プロパティ値をクリアするためのメソッド名を指定すると、Mooseにより自動的にその名前でメソッドが追加される
predicate 値が設定されているか判定するメソッド名 プロパティに値が設定されているかどうかを判定するためのメソッド名を指定すると、Mooseにより自動的にその名前でメソッドが追加される
coerce 0または1 1に設定した場合にはisaで指定した型以外の値が渡された場合に強制的な型変換を行う

 最後の部分(3)では、no Mooseを指定することでMoose関連の関数を名前空間から削除し、__PACKAGE__->meta->make_immutableでクラスを不変化させます。不変化させると、これ以降ではクラスへのプロパティの追加などはできなくなりますが、実行時にはクラスが高速に動作するようになります。

 次に、Mooseを使ってPersonから継承させたBaseballPlayerを見ていきましょう。こちらの場合にも、use Mooseで始まり、最後はno Moose__PACKAGE__->meta->make_immutableを呼び出しています。

[リスト6]Moose版BaseballPlayerクラス
package moosified::BaseballPlayer;
use Moose;
#(1)moosified::Personから継承させる
extends 'moosified::Person';

has 'team' => (
  is  => 'rw',
  isa => 'Str',
  default => 'none',
);
#(2)introduceをオーバーライドする
override 'introduce' => sub {
  my $self = shift;
  super();
  print "\tAnd I belong to " , $self->team() , ".\n";
};

# 省略

 Mooseで継承させるには、(1)のようにextends関数に継承元となるクラス名を指定します。メソッドをオーバーライドさせるには、(2)のようにoverrideメソッドを使用します。overrideで指定したメソッドからは、super()を使って継承元のメソッドを呼び出すことができますが、このときsuper()には引数を指定することができません(指定しても無視されます)。override指定したメソッドに引数が渡された場合には、それがそのまま継承元のメソッドに渡されます。

 overrideなどの、メソッドの振る舞いを変更することができる機能はメソッド修飾子と呼ばれます。メソッド修飾子には他にもbeforeafteraroundといったものが用意されています。fooメソッドに対してbeforeafteraroundを適用した例は次のようになります。

[リスト7]before、after、arroundの例
package Example;
use Moose;

sub foo {
  print "foo\n";
}
# (1)before
before 'foo' => sub { print "before foo\n"; };
# (2)after
after 'foo' => sub { print "after foo\n"; };
# (3)around
around 'foo' => sub {
  my $orig = shift;
  my $self = shift;
  print "before foo in around\n";
  # fooの呼び出し
  $self->$orig(@_);
  print "after foo in around\n";
};
# fooメソッドを呼び出す
Example->new->foo;

 ▼

実行結果
before foo
before foo in around
foo
after foo in around
after foo

(1)before

 beforeで指定したサブルーチンは、fooメソッドが呼び出される前に実行されます。一般的には、メソッドやプロパティの値チェックなどで使用されます。サブルーチンからの返値は無視されます。

(2)after

 afterで指定したサブルーチンは、fooメソッドが呼び出された後で実行されます。一般的には、ログを記録したりする場合などで使用されます。beforeと同様にサブルーチンからの返値は無視されます。

(3)around

 aroundでは、最初の引数に元のメソッド(この例だとfooメソッド)、2番目の引数にオブジェクト、それ以降では元のメソッドへの引数が渡されます。実行例からも分かるように、beforearoundの前、afteraroundの後に実行されます。

 aroundを使うと、引数の値によっては元のメソッドを呼び出さないこともできますし、返値を書き換えることもできるようになります。

 それでは、Moose版のPersonBaseballPlayerの動作を確認するスクリプトをmoosified_test.plという名前で定義してみます。

 内容はblessed_test.plとほとんど同じで、blessed::の部分をmoosified::に変更するだけでそのまま動作します。

 このスクリプトを実行し、出力される結果を確認しましょう。

[リスト8]moosified_test.plの実行
$ perl moosified_test.pl

 ▼

実行結果
Matsui
35
My name is Matsui, 35 years old.
My name is Suzuki, 36 years old.
        And I belong to Mariners.

 Mooseを使うとblessを使った場合に比べ、より簡潔な記述で、より多くのことを実現することができるようになりますが、その代償としてメモリ使用量の増加とコンパイル時の処理速度の低下がみられます。Moose自身にも最適化が加えられていますが、どうしても実行速度を向上させたい場合には、MouseClass::Accessor::Fastなどの選択肢もあります。

 特にMouseは、hasなどのクラス定義については、多くの部分でMooseとの互換性を保つように実装されています。

次のページ
Mooseを使用したCatalystの実装

この記事は参考になりましたか?

Webアプリケーションフレームワーク「Catalyst」入門連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 花田 善仁(ハナダ ヨシヒト)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/4734 2010/06/18 15:36

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー