2008年3月6日木曜日

Frozen Perl 2008メモその1:Introduction to OOP(オブジェクト指向Perl入門)

素晴らしい発表だった。

オブジェクト指向の入門、それもPerlで、となるとわかりやすい文献はなかなかない。文献はたくさんあるのだが、どれも「わかる人にしかわからない」というタイプのように思う。さらにカンファレンスで行われる「○○入門」がわかりやすかったためしがないので期待しないでいたら、これが実に初心者にやさしいものだった。

スライドが公開されている。ノートをたくさんとったのに……。

Perlのオブジェクト指向関係用語

(Mint注:この項はいきなりわからなくていいと思う)

  • 「オブジェクト」とは→bless()されたハッシュリファレンス
  • 「クラス」とは→パッケージ(package)
  • 「メソッド」とは→パッケージの中のサブルーチン(sub)

Personモジュールを使ったオブジェクト指向スクリプトの例

以下をperson.plという名前で保存する。

1: use Person;
2: my $watashi = Person->new();
3: $watashi->lastName( 'Yamada' );
4: $watashi->firstName( 'Taro' );
5: print $watashi->fullName();
  • 1行目:Person.pmを探してそれを読み込む
  • 2行目:「私は人間です」$watashiという変数を定義してPersonクラスに関連づける。このnew()というメソッドをコンストラクタという。
  • 3行目:「私の苗字は山田です」ややこしいことを書くと、$watashiというオブジェクトのlastNameメソッドを使って$watashiのlastName(姓)という属性(attribute)がYamadaであると指定をする(後で出てくるがこのfirstName()は特にアクセサと呼ばれる)。
  • 4行目:「私の名前は太郎です」3行目と同じ。firstName(ファーストネーム)は姓名の名のほうです。
  • 5行目:「私のフルネーム」を出力する。

Personモジュールを作る

以下をPerson.pmという名前で保存する。

1:  package Person;
2: sub new {
3: my $class = shift;
4: my $self = bless {}, $class;
5: return $self;
6: }
7: sub lastName {
8: my ( $self, $lastName ) = @_;
9: if ( defined $lastName ) {
10: $self->{ lastName } = $lastName ;
11: }
12: return $self->{ lastName };
13: }
14: sub firstName {
15: my ( $self, $firstName ) = @_;
16: if ( defined $firstName ) {
17: $self->{ firstName } = $firstName ;
18: }
19: return $self->{ firstName };
20: }
21: sub fullName {
22: my $self = shift;
23: return $self->firstName() . " " . $self->lastName();
24: }
25: 1;

ひとつひとつのかたまりについて見て行く。

2:  sub new {
3: my $class = shift;
4: my $self = bless {}, $class;
5: return $self;
6: }

このnew()というサブルーチン(オブジェクト指向のメソッド)がコンストラクタ。newでもatarashiiでもなんでもいいが、慣例でnewを使う。

7:  sub lastName {
8: my ( $self, $lastName ) = @_;
9: if ( defined $lastName ) {
10: $self->{ lastName } = $lastName ;
11: }
12: return $self->{ lastName };
13: }

この例では、

$watashi->lastName();
とした場合は$watashiの姓を返すし
$watashi->lastName( 'Yamada' );
とした場合は$watashiの姓をYamadaにする。

こうやって、値を取得する(set)ものと値を設定する(get)ための機能が対になったものを特にアクセサと呼んだりする(Java由来の概念だと思う)。

次のfirstName()も同じこと。

14: sub firstName {
15: my ( $self, $firstName ) = @_;
16: if ( defined $firstName ) {
17: $self->{ firstName } = $firstName ;
18: }
19: return $self->{ firstName };
20: }

さて、姓名を返すfullName()の登場。


21: sub fullName {
22: my $self = shift;
23: return $self->firstName() . " " . $self->lastName();
24: }

この例では、

$watashi->fullName;
とすると$watashiの姓名(Taro Yamada)を返す。
23: return $self->firstName() . " " . $self->lastName();
のように、メソッドを呼ぶことに注意。つまり
23: return $self->{ firstName } . $self->{ lastName };
とは普通書かない。

継承

Personクラスを継承するFriendクラスをFriend.pmとして定義する。こうすると、Personクラスで定義されているすべてのメソッドをFriendクラスで使うことができる。「私の友達はみんな人間である」ということ。

1: package Friend;
2: use Person;
3: @ISA = qw( Person );
4: 1;

baseモジュールを使うと、Friend.pmの同じ内容をもっと簡単に書ける。

1: package Friend;
2: use base qw( Person );
3: 1;

以上でFriendオブジェクトを作る準備ができたのでfriend.plも作る。

1: use Friend;
2: my $friend = Friend->new();
3: print ref $friend; # "Friend"を出力
4: $friend->firstName( 'Taro' );
5: print $friend->firstName(); # "Taro"を出力

FriendクラスにfirstNameというメソッドは登場しないが、Personクラスを継承しているのでfirstNameというメソッドをFriendオブジェクトに対して使える。

メソッドのオーバーライド

Friendクラスに対し、firstNameメソッドとlastNameメソッドはPersonクラスから継承したものを使いたい。しかしfullNameメソッドはFriendクラスで独自に定義したものを使いたい。

こういうときにFriendクラスでfullNameメソッドを定義できる。親クラス(Person)のfullNameメソッドをオーバーライドする(親クラスに優先させる)という。つまり、Friend.pmはこうなる。

1: package Friend;
2: use Person;
3: @ISA = qw( Person );
4: sub fullName {
5: my $self = shift;
6: return "My friend " . $self->firstName() . " " . $self->lastName();
7: }
8: 1;

そして、friend.plをこう書き換える。

1: use Friend;
2: my $friend = Friend->new;
3: $friend->firstName( 'Taro' );
4: $friend->lastName( 'Yamada' );
5: print $friend->fullName;

fullNameメソッドがオーバーライドされているため、5行目は

My Friend Taro Yamada
を返す。

SUPERクラス

fullNameメソッドはPersonクラスとFriendクラスの両方で定義されている。Friendクラスの中で親(Person)クラスのfullNameメソッドを使いたいときは、SUPERという特別なクラス名を使う。

これがPerson.pmのfullName。

21: sub fullName {
22: my $self = shift;
23: return $self->firstName() . " " . $self->lastName();
24: }

これが先ほどのFriend.pmのfullName。6行目が上の23行によく似ていることに着目。

4: sub fullName {
5: my $self = shift;
6: return "My friend " . $self->firstName() . " " . $self->lastName();
7: }

この6行目は、Person.pmのfullNameを借りる形でこう書き直せる。

4: sub fullName {
5: my $self = shift;
6: return "My friend " . $self->SUPER::fullName();
7: }

リンク

Perlオブジェクト指向プログラミングがおすすめです。

0 コメント:

コメントを投稿