Moose(Mouse)の基本。アクセサのコードを読んでみる

モダンPerl入門 (業務で使う実用的な Perl の“すべて”) を読んで、
改めて Moose を勉強中です。
今回は、(Moose 本体でなくて互換・軽量版の)Mouse.pm
生成してくれるアクセサのメソッドのコードを確認してみました。

is => 'rw'

has 'attr01' => (
    is      =>   'rw',
);
基本となる read/write 可能なアトリビュートの場合。
↑が Mouse に伝える定義で、↓が実際に生成されるアクセサのコード。
値を更新(代入)するときは、scalar @_ が 2 になっているはず。
sub attr01 {
  if ( @_ >= 2 ) {
    return $_[0]->{'attr01'} = $_[1];
  }
  return $_[0]->{'attr01'};
}

is => 'ro'

has 'attr02' => (
    is      =>   'ro',
);
readonly にした場合、値を更新しようとすると confess でエラーが発生します。
sub attr02 {
  confess "Cannot assign a value to a read-only accessor" if scalar(@_) >= 2;
  return $_[0]->{'attr02'};
}

isa => 'Int'

has 'attr03' => (
    is      =>   'rw',
    isa     =>   'Int',
);
isa で型(Int)を指定した場合。
更新時は代入前に verify_type_constraint_error が呼ばれて、型チェックが行われます。
$name にはアトリビュートの名前が入ります。
$attribute は、Mouse::Meta::Attribute オブジェクトです。
sub attr03 {
  if ( @_ >= 2 ) {
    my $val = $_[1];
    local $_ = $val;
    unless ( $constraint->() ) {
      $attribute->verify_type_constraint_error( $name, $_, $attribute->type_constraint );
    }
    return $_[0]->{'attr03'} = $val;
  }
  return $_[0]->{'attr03'};
}

lazy => 1, default => 'value'

has 'attr04' => (
    is      =>   'rw',
    lazy    =>   1,
    default =>   'value',
);
デフォルト値を即値 'value' で指定した場合。
lazy なので、オブジェクト生成時でなくて、参照時に値が代入されます。
初回の参照前に、予め値を更新(代入)していれば、このデフォルト値は使用されません。
sub attr04 {
  if ( @_ >= 2 ) {
    return $_[0]->{'attr04'} = $_[1];
  }
  $_[0]->{'attr04'} = $default if !exists $_[0]->{'attr04'};
  return $_[0]->{'attr04'};
}

lazy => 1, default => sub {}

has 'attr05' => (
    is      =>   'rw',
    lazy    =>   1,
    default =>   sub {},
);
デフォルト値を関数へのリファレンスで指定した場合。
初回の参照時(未更新の場合)に関数が呼び出されます。
sub attr05 {
  if ( @_ >= 2 ) {
    return $_[0]->{'attr05'} = $_[1];
  }
  $_[0]->{'attr05'} = $default->( $_[0] ) if !exists $_[0]->{'attr05'};
  return $_[0]->{'attr05'};
}
※この lazy に呼び出される関数を、クラス定義時でなくてインスタンス生成後に
 lazy に差し替える(上書きする)方法が欲しいのだけど、ムリなのかな……。
 

lazy => 1, builder => 'method'

has 'attr06' => (
    is      =>   'rw',
    lazy    =>   1,
    builder =>   'method',
);
ビルダーのメソッド名を指定した場合。
sub attr06 {
  if ( @_ >= 2 ) {
    return $_[0]->{'attr06'} = $_[1];
  }
  $_[0]->{'attr06'} = $_[0]->$builder if !exists $_[0]->{'attr06'};
  return $_[0]->{'attr06'};
}

trigger => sub {}

has 'attr07' => (
    is      =>   'rw',
    trigger =>   sub {},
);
更新時に呼び出される関数を指定した場合。
トリガーの第1引数はオブジェクト(インスタンス)、第2引数は更新後の値、
第3引数にはこのアトリビュートの Mouse::Meta::Attribute オブジェクトが入る。
sub attr07 {
  if ( @_ >= 2 ) {
    $_[0]->{'attr07'} = $_[1];
    $trigger->( $_[0], $_[1], $attribute );
  }
  return $_[0]->{'attr07'};
}

handles => []

has 'attr08' => (
    is      =>   'rw',
    handles =>   [ 'method1', 'method2' ],
);
アトリビュートの値に対するメソッドを export するようなものか。
sub attr08 {
  if ( @_ >= 2 ) {
    return $_[0]->{'attr08'} = $_[1];
  }
  return $_[0]->{'attr08'};
}
sub method1 {
  my $self = shift;
  $self->attr08->method1(@_);
}
sub method2 {
  my $self = shift;
  $self->attr08->method2(@_);
}

handles => {}

has 'attr09' => (
    is      =>   'rw',
    handles =>   { alias1 => 'method1', alias2 => 'method2',  },
);
アトリビュートの値に対するメソッドについて、別名を付けて定義する。
sub attr09 {
  if ( @_ >= 2 ) {
    return $_[0]->{'attr09'} = $_[1];
  }
  return $_[0]->{'attr09'};
}
sub alias1 {
  my $self = shift;
  $self->attr09->method1(@_);
}
sub alias2 {
  my $self = shift;
  $self->attr09->method2(@_);
}

clearer => 'clear_***'

has 'attr10' => (
    is      =>   'rw',
    clearer =>   'clear_attr10',
);
値をクリアするメソッドを作ってくれる。
sub attr10 {
  if ( @_ >= 2 ) {
    return $_[0]->{'attr10'} = $_[1];
  }
  return $_[0]->{'attr10'};
}
sub clear_attr10 { delete( $_[0]->{'attr10'} ) }

predicate => 'has_***'

has 'attr11' => (
    is          =>   'rw',
    predicate   =>   'has_attr11',
);
値が定義済(代入済)か確認するメソッドを作ってくれる。
sub attr11 {
  if ( @_ >= 2 ) {
    return $_[0]->{'attr11'} = $_[1];
  }
  return $_[0]->{'attr11'};
}
sub has_attr11 { exists( $_[0]->{'attr11'} ) }

CPAN ドキュメントはこちら:MooseMouse

しかし、牧さんの モダンPerl入門 良い本です!
Moose に関しても、これだけ揃った日本語解説は初めてと思います。
レベルは少々高いので、『これから初めてのプログラミング言語として Perl を学ぼう』
としている人には向かないですが、Perl か、または他の言語を一通り使える方が、
現在の「モダンな」Perl の状況を学ぶのには最適な本と思います。

モダンPerl入門 (業務で使う実用的な Perl の“すべて”)
牧 大輔 (著)
出版社: 翔泳社 (2009/2/10)
ISBN-10: 4798119172
発売日: 2009/2/10

Amazon で『モダンPerl入門』を購入

川崎は、今は昔、ソフトバンク版の Perlプログラミング を買って端から端までくまなく愛読して
Perl を学んできたクチなのですが、さすがにもう内容も古く、今から学ぶ人には
あまりオススメできる本ではありません。(基本ではあると思うが、歴史に近いか)
しかし、モダンPerl入門 は、モダン Perl における『Perl プログラミング』に匹敵する本ではないかと思います。


ブログ気持玉

クリックして気持ちを伝えよう!

ログインしてクリックすれば、自分のブログへのリンクが付きます。

→ログインへ

なるほど(納得、参考になった、ヘー)
驚いた
面白い
ナイス
ガッツ(がんばれ!)
かわいい

気持玉数 : 8

なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー)
ナイス

この記事へのコメント

この記事へのトラックバック