これはMoritz Lenz氏のWebサイトPerlgeek.deで公開されているブログ記事"Perl 5 to 6" Lesson 05 - Objects and Classesの日本語訳です。
原文はCreative Commons Attribution 3.0 Germanyに基づいて公開されています。
本エントリにはCreative Commons Attribution 3.0 Unportedを適用します。
Original text: Copyright© 2008-2010 Moritz Lenz
Japanese translation: Copyright© 2011 SATOH Koichi
NAME
"Perl 5 to 6" Lesson 05 - オブジェクトとクラス
SYNOPSIS
class Shape {
method area { ... } # リテラル '...'
has $.colour is rw;
}
class Rectangle is Shape {
has $.width;
has $.height;
method area {
$!width * $!height;
}
}
my $x = Rectangle.new(
width => 30.0,
height => 20.0,
colour => 'black',
);
say $x.area; # 600
say $x.colour; # black
$x.colour = 'blue';
DESCRIPTION
Perl6にはPerl5よりずっと洗練されたオブジェクトモデルがあります。クラス、ロール、アトリビュートやメソッドのためのキーワードがあり、カプセル化されたプライベートなアトリビュートやメソッドがあります。 これは(Perl6のオブジェクトシステムに影響を受けた)Perl5のMooseモジュールにとてもよく似ています。
クラスを宣言する方法は2通りあります。
class ClassName;
# ここにクラス定義を書く
1つはclass ClassName;
で始まるもので、ファイルの終端までを範囲とします。
もう1つはクラス名にブロックが続くもので、ブロックの中身がクラス定義とみなされます。
class YourClass {
# ここにクラス定義を書く
}
# 他のクラスやコード
メソッド
メソッドはmethod
キーワードで宣言されます。メソッド中ではself
キーワードを使って呼び出し元オブジェクト(Invocant)を参照できます。
シグネチャリストの最初のパラメータに:
を付けることで、読み出し元オブジェクトに別名を付けて参照することもできます。
パブリックなメソッドは引数を取らない場合は$object.method
、引数を取る場合は$object.method(@args)
あるいは$object.method: @args
という構文で呼び出すことができます。
class SomeClass {
# 何もせずに呼び出し元オブジェクトを返す
method foo {
return self;
}
method bar($s: ) {
return $s;
}
}
my SomeClass $x .= new;
$x.foo.bar # $xと同じ
(my SomeClass $x .= new
はmy SomeClasss $x .= SomeClass.new
の省略形です。型宣言がSomeClassクラスを表すオブジェクトである「型オブジェクト」を補完してくれます)
メソッドはサブルーチンと同様に他の引数も取ることができます。
プライベートメソッドはmethod !method_name
で宣言され、self!method_name
で呼び出せます。
class Foo {
method !private($frob) {
return "Frobbed $frob";
}
method public {
say self!private("foo");
}
}
プライベートメソッドをクラスの外から呼び出すことはできません。
アトリビュート
アトリビュートはhas
キーワードで宣言され、シジルの後に特別な文字である「ツイジル(Twigil)」が付きます。プライベートアトリビュートには!
、パブリックアトリビュートには.
が付きます。
パブリックアトリビュートは単にパブリックなアクセサを持つプライベートアトリビュートです。
したがってアトリビュートの値を変更したい場合は、!
ツイジルを使ってアクセサを介さずアトリビュート自身にアクセスする必要があります(アクセサがis rw
である場合を除く)。
class SomeClass {
has $!a;
has $.b;
has $.c is rw;
method set_stuff {
$!a = 1; # OK、クラス内からのアトリビュートに対する書き込み
$!b = 2; # 同上
$.b = 3; # エラー、読み出し専用アクセサには書き込めない
}
method do_stuff {
# パブリックな名前の代わりにプライベートな名前を使えます
# $!bと$.bは同じものを表します
return $!a + $!b + $!c;
}
}
my $x = SomeClass.new;
say $x.a; # エラー!
say $x.b; # OK
$x.b = 2; # エラー!
$x.c = 3; # OK
継承
継承はis
トレイトを使って行います。
class Foo is Bar {
# FooクラスはBarクラスから継承する
...
}
一般的な継承ルールはすべて適用されます——メソッドはまず実際の型の中で探索され、見つからない場合は親クラスを再帰的に探索します。派生クラスの型は親クラスの型としても振る舞います:
class Bar { }
class Foo is Bar { }
my Bar $x = Foo.new();
この例では$x
の型はBar
であり、「すべてのFoo
はBar
である」ためFoo
のオブジェクトが代入できます。
複数のクラスから多重継承できます:
class ArrayHash is Hash is Array {
...
}
ロールと合成
世界は階層的にはできていませんから、何もかもを継承階層に押し込めるのが難しいこともあります。 これがPerl6にロールがある理由の1つです。ロールはクラスにとてもよく似ていますが、直接オブジェクトを作ることはできません。 クラスは型適合性の保証がその第一の目的ですが、ロールはコードの再利用を第一義としています。
role Paintable {
has $.colour is rw;
method paint { ... }
}
class Shape {
method area { ... }
}
class Rectangle is Shape does Paintable {
has $.width;
has $.height;
method area {
$!width * $!height;
}
}
SEE ALSO
http://perlcabal.org/syn/S12.html http://perlcabal.org/syn/S14.html
コメント
コメントを投稿