Skip to content

Latest commit

 

History

History
1828 lines (1220 loc) · 61.6 KB

perlootut.pod

File metadata and controls

1828 lines (1220 loc) · 61.6 KB

NAME

perlootut - Perl でのオブジェクト指向プログラミングのチュートリアル

DATE

この文書は 2011 年 2 月に作成され、最後に大きく見直されたのは 2013 年 2 月です。

もし将来これを読んでいる場合、最新版は変更されている可能性があります。 このバージョンではなく、Perl の最新安定リリースの perlootut 文書を 読むことから始めることを勧めます。

DESCRIPTION

この文書は Perl でのオブジェクト指向プログラミングを紹介します。 これはオブジェクト指向設計の背後にあるコンセプトの概説から始めます。 それから Perl が提供するものの上に構築されている、 CPAN にあるいくつかの OO システムを紹介します。

デフォルトでは、Perl の組み込みの OO システムはとても最小限です; ほとんどの 作業を自分でする必要があります。 この最小限主義は 1994 年には十分意味のあるものでしたが、Perl 5.0 から 時が経つにつれて、Perl OO に多くの共通のパターンが見られるようになりました。 幸い、Perl の柔軟性により、Perl OO システムの豊かなエコシステムが 発展しました。

裏で Perl OO がどのように動作するのかを知りたい場合は、perlobj 文書が 本質的な詳細について説明しています。

この文書は、Perl の文法、変数型、演算子、サブルーチン呼び出しの基本について 既に理解していると仮定しています。 まだこれらのコンセプトについてまだ理解していないなら、まず perlintro を 読んでください。 perlsyn, perlop, perlsub 文書も読むべきでしょう。

OBJECT-ORIENTED FUNDAMENTALS

(オブジェクト指向の基本)

ほとんどのオブジェクトシステムは多くの共通の概念を共有しています。 おそらく以前に「クラス」、「オブジェクト」、「メソッド」、属性といった 用語について聞いたことがあるでしょう。 概念の理解は、オブジェクト指向のコードを読み書きするよりも遥かに容易です。 既にこれらの用語に親しんでいても、この章に目を通すべきです; なぜなら Perl の OO 実装の用語でそれぞれの概念を説明しているからです。

Perl の OO システムはクラスベースです。 クラスベース OO はかなり一般的です。 これは Java, C++, C#, Python, Ruby およびその他の多くの言語で使われています。 その他のオブジェクト指向パラダイムもあります。 JavaScript は、その他のパラダイムを使っている最も有名な言語です。 JavaScript の OO システムはプロトタイプベースです。

Object

(オブジェクト)

オブジェクト は、データと、そのデータを操作するサブルーチンを一つに まとめたデータ構造です。 オブジェクトのデータは 属性 と呼ばれ、サブルーチンは メソッド と 呼ばれます。 オブジェクトは名詞と考えることができます (人、web サービス、 コンピュータなど)。

オブジェクトは単一のものを表現します。 たとえば、あるオブジェクトがファイルを表現しているとします。 ファイルオブジェクトの属性はパス、内容、最終更新時刻といったものになります。 オブジェクトのパスが "/etc/hostname" になるような、 "foo.example.com" という名前のマシンの /etc/hostname を表現する オブジェクトを作る場合、その内容は "foo\n" で、最終更新時刻は紀元から 1304974868 秒といったものになります。

ファイルに結びつけられたメソッドは rename()write() と いったものになります。

Perl ではほとんどのオブジェクトはハッシュですが、推奨する OO システムは これについて気にする必要がないようにします。 実際には、オブジェクトの内部構造は不透明であると考えるのが最良です。

Class

(クラス)

クラス はあるカテゴリのオブジェクトの振る舞いを定義します。 クラスは("File" のような)カテゴリを表す名前です; またクラスは そのカテゴリのオブジェクトの振る舞いを定義します。

全てのオブジェクトは何らかのクラスに属します。 例えば、/etc/hostname オブジェクトは File クラスに属します。 特定のオブジェクトを作りたい場合、そのクラスから始めて、オブジェクトを 構築(construct) または インスタンス化 (instantiate) します。 特定のオブジェクトはしばしばクラスの インスタンス (instance) と 呼ばれます。

Perl では、どのパッケージもクラスになれます。 クラスであるパッケージとそうでないパッケージの違いは、パッケージがどのように 使われるかによります。 以下は File クラスのための「クラス宣言」です:

package File;

Perl では、オブジェクトの構築のための特別なキーワードはありません。 しかし、CPAN のほとんどの OO モジュールは、新しいオブジェクトの構築に new() という名前のメソッドを使います:

my $hostname = File->new(
    path          => '/etc/hostname',
    content       => "foo\n",
    last_mod_time => 1304974868,
);

(-> 演算子について心配しないでください; 後で説明します。)

Blessing

(bless)

既に述べたように、ほとんどの Perl オブジェクトはハッシュですが、 オブジェクトはどの Perl データ型 (スカラ、配列など)のインスタンスも可能です。 普通のデータ構造のオブジェクトへの変換は、データ構造に Perl の bless 関数を 使うことによる bless によって行われます。

一からオブジェクトを構築しないことを強く勧めますが、bless という 用語は知っておくべきです。 bless された データ構造 (またの名を「リファレンス先」)はオブジェクトです。 時々、オブジェクトは「クラスに bless された」と表現します。

一旦リファレンス先が bless されると、Scalar::Util コアモジュールの blessed 関数はそのクラス名を返します。 このサブルーチンは、オブジェクトが和されるとオブジェクトのクラスを返し、 さもなければ偽を返します。

use Scalar::Util 'blessed';

print blessed($hash);      # undef
print blessed($hostname);  # File

Constructor

(コンストラクタ)

コンストラクタ は新しいオブジェクトを作成します。 コンストラクタのための文法を提供しているその他の言語と異なり、Perl では クラスのコンストラクタは単なるメソッドです。 ほとんどの Perl クラスはコンストラクタの名前として new を使います:

my $file = File->new(...);

Methods

(メソッド)

オブジェクトを操作するサブルーチンが メソッド であるということは 既に学んでいます。 メソッドはオブジェクトが する ことと考えることができます。 オブジェクトが名詞なら、メソッドは動詞 (保存する、表示する、開く) です。

Perl では、メソッドは単にクラスのパッケージにあるサブルーチンです。 メソッドは常に最初の引数としてオブジェクトを受け取るように書かれます:

sub print_info {
    my $self = shift;

    print "This file is at ", $self->path, "\n";
}

$file->print_info;
# The file is at /etc/hostname

メソッドを特別なものにしているのは、どのように呼び出されるか です。 矢印演算子 (->) は、メソッドとして呼び出していることを Perl に 知らせます。

メソッド呼び出しをするとき、Perl はメソッドの 呼び出し元 (invocant) を 最初の引数として渡すように用意します。 呼び出し元 とは矢印の左側にあるものの名前です。 呼び出し元はクラス名とオブジェクトのどちらかです。 また、メソッドに追加の引数も渡せます:

sub print_info {
    my $self   = shift;
    my $prefix = shift // "This file is at ";

    print $prefix, ", ", $self->path, "\n";
}

$file->print_info("The file is located at ");
# The file is located at /etc/hostname

Attributes

(属性)

各クラスは 属性 を定義します。 オブジェクトをインスタンス化するとき、これらの属性に値を代入します。 例えば、各 File オブジェクトはパスを持ちます。 属性は時々 プロパティ (properties) と呼ばれます。

Perl には属性のための特別な文法はありません。 内部では、属性はしばしばオブジェクトの基となっているハッシュのキーとして 保管されますが、これについて気にすることはありません。

属性には アクセサ (accessor) メソッドを経由してのみアクセスすることを 勧めます。 これはそれぞれの属性の値を取得または設定するメソッドです。 既に、前述した print_info() の例で、$self->path を 呼び出しているのを見ています。

ゲッター (getter) と セッター (setter) という用語も見るかも知れません。 これらはアクセサの種類です。 ゲッターは属性の値を取得し、セッターは設定します。 セッターに関する別名は ミューテータ (mutator) です。

属性は典型的には読み込み専用または読み書き可能として定義されます。 読み込み専用属性はオブジェクトが最初に作成されるときにのみ設定でき、 読み書き可能属性はいつでも変更できます。

属性の値それ自身が他のオブジェクトかも知れません。 例えば、最終更新時刻を数値として返す代わりに、File クラスはその値を 表現する DateTime オブジェクトを返すかも知れません。

設定可能な属性が一切公開されていないクラスも可能です。 全てのクラスが属性とメソッドを持っているというわけではありません。

Polymorphism

(多態性)

多態性 (polymorphism) は二つの異なるクラスが API を共有しているということを 示す変わった方法です。 例えば、どちらも print_content() メソッドを持つ、File クラスと WebPage クラスを持てます。 このメソッドはクラスごとに異なった出力を生成するかも知れませんが、共通の インターフェースを共有します。

二つのクラスはいろいろな意味で異なっているかも知れませんが、 print_content() メソッドを呼び出すときには、これらは同じです。 これは、どちらのクラスのオブジェクトに対しても print_content() を 呼び出そうとすることができて、オブジェクトがどのクラスに属しているかを 知る必要がないと言うことです!

多態性はオブジェクト指向設計の鍵となる概念の一つです。

Inheritance

(継承)

継承 は既にあるクラスの特殊版を作成できるようにします。 継承は他のクラスのメソッドと属性を再利用して新しいクラスを 作成できるようにします。

例えば、File から 継承 した File::MP3 クラスを作成できます。 File::MP3 (is-a) Fileより特殊な 型です。 全ての mp3 ファイルはファイルですが、全てのファイルが mp3 ファイルというわけではありません。.

継承関係はしばしば 親-子 または スーパークラス/サブクラス 関係として 参照されます。 子は親クラスとの is-a 関係を持つと表現することがあります。

FileFile::MP3スーパークラス で、File::MP3Fileサブクラス です。

package File::MP3;

use parent 'File';

parent モジュールは、Perl で継承関係を定義するいくつかの方法のひとつです。

Perl は多重継承を認めています; つまり、クラスは複数の親から継承できます。 これは可能ですが、行わないように強く勧めます。 一般的に、多重継承で行えることは全て、ロール を使うことでより きれいな形で行えます。

あるクラスに対して複数のサブクラスを定義することは何も悪くないことに 注意してください。 これは一般的でかつ安全です。 例えば、mp3 ファイルの異なった種類を区別するために、 File::MP3::FixedBitrate クラスと File::MP3::VariableBitrate クラスを 定義できます。

Overriding methods and method resolution

(メソッドのオーバーライドとメソッド解決)

継承は二つのクラスでコードを共有できるようにします。 デフォルトでは、親クラスの全てのメソッドは子でも利用可能です。 子は、独自の実装を提供することで親のメソッドを明示的に オーバーライド (override) できます。 例えば、File::MP3 オブジェクトがあれば、File からの print_info() メソッドがあります:

my $cage = File::MP3->new(
    path          => 'mp3s/My-Body-Is-a-Cage.mp3',
    content       => $mp3_data,
    last_mod_time => 1304974868,
    title         => 'My Body Is a Cage',
);

$cage->print_info;
# The file is at mp3s/My-Body-Is-a-Cage.mp3

返り値に mp3 のタイトルを含めたい場合、メソッドをオーバーライドできます:

package File::MP3;

use parent 'File';

sub print_info {
    my $self = shift;

    print "This file is at ", $self->path, "\n";
    print "Its title is ", $self->title, "\n";
}

$cage->print_info;
# The file is at mp3s/My-Body-Is-a-Cage.mp3
# Its title is My Body Is a Cage

どのメソッドが使われるべきかを決定する処理は、メソッド解決 (method resolution) と呼ばれます。 Perl が行うことは、まずオブジェクトのクラス (この場合は File::MP3) を 見ます。 このクラスにメソッドが定義されていれば、そのクラスのメソッドが呼び出されます。 さもなければ、Perl は順番に親クラスを見ます。 File::MP3 の場合、唯一の親は File です。 File::MP3 がメソッドを定義しておらず、File が定義しているなら、 Perl は File のメソッドを呼び出します。

FileDataSource から継承され、これが Thing から継承されていれば、 Perl はもし必要なら「チェーンをたどって」探し続けます。

子から親メソッドを明示的に呼び出すことは可能です:

package File::MP3;

use parent 'File';

sub print_info {
    my $self = shift;

    $self->SUPER::print_info();
    print "Its title is ", $self->title, "\n";
}

SUPER:: は、File::MP3 クラスの継承チェーンから print_info() を 探すように Perl に伝えます。 このメソッドを実装している親クラスが見つかると、そのメソッドが 呼び出されます。

以前に多重継承について述べました。 多重継承の主な問題は、メソッド解決が非常に込み入っているということです。 さらなる詳細については perlobj を参照してください。

Encapsulation

(カプセル化)

カプセル化 は、オブジェクトを不透明にする考え方です。 他の開発者があなたのクラスを使うとき、どのように 実装されているかを 知る必要はなく、単に 何を するかを知る必要があるだけです。

カプセル化はいくつかの理由で重要です。 まず、これにより公的な API を内部の実装から分離できます。 これにより、API を壊すことなく実装を変更できます。

次に、クラスが十分にカプセル化されていれば、サブクラス化が容易になります。 理想的には、サブクラスは親クラスが使っているオブジェクトデータに アクセスするのに同じ API を使います。 実際には、サブクラス化は時々カプセル化に違反しますが、よい API は その必要性を最小限にします。

既に、ほとんどの Perl オブジェクトは内部ではハッシュとして実装されていると 述べました。 カプセル化の原則は、このことに依存するべきではないと伝えています。 代わりに、ハッシュのデータにアクセスするためにアクセサメソッドを使います。 後に推奨するオブジェクトシステムは全てアクセサメソッドの生成を自動化します。 これらの一つを使うなら、オブジェクトをハッシュとして直接アクセスする必要は ないはずです。

Composition

(包含)

オブジェクト指向のコードでは、しばしばあるオブジェクトが他のオブジェクトを 参照しています。 これは 包含 (composition)、または has-a 関係と呼ばれます。

既に、File クラスの last_mod_time アクセサが DateTime オブジェクトを 返すかも知れないことに触れました。 これは包含の完璧な例です。 さらに進めて、pathcontent アクセサもオブジェクトを返すようにも できます。 そして File クラスはいくつかのその他のオブジェクトの 包含 になります。

Roles

(ロール)

ロール は、クラスが 何か ではなく、クラスが 何をするか です。 ロールは Perl では比較的新しいですが、かなり人気になってきています。 ロールはクラスに 適用 されます。 クラスがロールを 消費 (consume) するということもあります。

ロールは多態性を提供するための継承の代替策です。 二つのクラス RadioComputer があると考えます。 どちらもオン/オフするスイッチがあります。 これをクラス定義でモデル化したいとします。

Machine のように、共通の親から両方のクラスを継承することもできますが、 全ての機械にオン/オフスイッチがあるわけではありません。 HasOnOffSwitch と呼ばれる親クラスを作ることもできますが、とても 不自然です。 ラジオとコンピュータはこの親の特殊化ではありません。 この親は実際にはかなりおかしなものです。

これはロールの出番です。 HasOnOffSwitch ロールを作って両方のクラスに適用することは とても合理的です。 このロールは turn_on()turn_off() メソッドを提供するような 既知の API を定義します。

Perl にはロールを記述する組み込みの方法はありません。 以前は、人々は我慢して多重継承を使っていました。 最近は、ロールを使うためのいくつかの良い選択肢が CPAN にあります。

When to Use OO

(いつ OO を使うか)

オブジェクト指向は全ての問題に対する最良の解法というわけではありません。 Perl Best Practices (copyright 2004, Published by O'Reilly Media, Inc.) において、Damian Conway は OO が問題に正しく適応するかどうかを決定するときに 使う基準の一覧を提供しています:

  • 設計しているシステムが大きいか、大きくなりそう。

  • データが明らかな構造に集合できる; 特にそれぞれの集合が大量のデータを持つ。

  • 様々な型のデータ集合が、継承と多態性を使うことが容易な自然な階層を形成する。

  • 多くの異なった操作を適用するデータがある。

  • データの種類に関係する同じ一般的な操作をする必要があるが、操作を適用する データの特定の種類に依存して少しずつ変化がある。

  • 後で新しいデータ型を追加する必要がありそう。

  • データ間の典型的な相互作用は演算子によって最もよく表現される。

  • システムの独立した要素の実装が時間につれて変化しそう。

  • システムの設計が既にオブジェクト指向である。

  • 多くのプログラマがこのコードモジュールを使う。

PERL OO SYSTEMS

(Perl の OO システム)

前述したように、Perl の組み込みの OO システムは非常に最小限ですが、 一方とても柔軟です。 年を重ねるにつれて、多くの人々がより多くの機能と利便性を提供するために Perl の組み込みのシステムの上に構築されたシステムを開発しました。

私たちはこれらのシステムの一つを使うことを強く勧めます。 それらの中の最小限のものでも多くの繰り返される定型文を排除できます。 Perl でクラスを一から書く本当にいい理由というものはありません。

これらのシステムの基礎となる内部に興味があるなら、 perlobj を 調べてください。

Moose

Moose は自分自身を「Perl 5 のためのポストモダンオブジェクトシステム」と 宣伝しています。 怖がらなくても大丈夫です; 「ポストモダン」というのはラリーが Perl のことを 「最初のポストモダンコンピュータ言語」と説明したことにちなんでいます。

Moose は完全でモダンな OO システムを提供します。 その最大の影響元は Common Lisp Object System ですが、Smalltalk およびその他の いくつかの言語からもアイデアを借りています。 Moose は Stevan Little によって作成され、彼の Raku OO 設計に関する 作業から多くを引いています。

以下は Moose を使った File クラスです:

package File;
use Moose;

has path          => ( is => 'ro' );
has content       => ( is => 'ro' );
has last_mod_time => ( is => 'ro' );

sub print_info {
    my $self = shift;

    print "This file is at ", $self->path, "\n";
}

Moose は多くの機能を提供します:

  • Declarative sugar

    (構文糖)

    Moose はクラスを定義するために、宣言的な「糖」の層を提供します。 この糖は、クラスがより簡単に、使いやすくなるようにするための単に エクスポートされた関数の集合です。 これは Perl が どのように クラスを実装するのかを教えるように するのではなく、クラスが 何を するかを表現するようにします。

    has() サブルーチンは属性を定義し、Moose は自動的にそれらの属性のための アクセサを作成します。 また、new() メソッドの面倒も見ます。 このコンストラクタは宣言された属性について知っているので、 新しい File を作成するときにそれを設定できます。

  • Roles built-in

    (組み込みのロール)

    Moose はクラスを定義するのと同じようにロールを定義できます:

    package HasOnOffSwitch;
    use Moose::Role;
    
    has is_on => (
        is  => 'rw',
        isa => 'Bool',
    );
    
    sub turn_on {
        my $self = shift;
        $self->is_on(1);
    }
    
    sub turn_off {
        my $self = shift;
        $self->is_on(0);
    }
  • A miniature type system

    (小型の型システム)

    前述の例では、is_on 属性を作成するときに has()isa => 'Bool' を渡します。 これは Moose に、この属性は真偽値でなければならないということを示します。 これに不正な値を設定しようとすると、エラーを投げます。

  • Full introspection and manipulation

    (完全なイントロスペクションと操作)

    Perl の組み込みのイントロスペクション機能はかなり最低限です。 Moose はこれらの上に構築され、クラスのための完全なイントロスペクション 層を作成します。 これにより、「File クラスに実装されているメソッドは何?」といった問い合わせが できます。 また、クラスをプログラムで修正できます。

  • Self-hosted and extensible

    (セルフホスティングと拡張性)

    Moose は自分自身を自身のイントロスペクション API を使って記述しています。 かっこいい技という以外に、これは Moose 自身を使って Moose を 拡張できるということです。

  • Rich ecosystem

    (豊かなエコシステム)

    CPAN の MooseX 名前空間に、Moose 拡張の豊かなエコシステムがあります。 さらに、CPAN の多くのモジュールは既に Moose を使っていて、そこから学べる 多くの例を提供しています。

  • Many more features

    (さらに多くの機能)

    Moose はとても強力なツールで、その機能の全てについてここで触れることは できません。 さらに学ぶために、Moose の文書を Moose::Manual から 読むことを勧めます。

もちろん、Moose は完璧ではありません。

Moose によってコードの読み込みが遅くなることがあります。 Moose 自身が小さくなく、またクラスを定義するときに 大量 の コードを生成します。 このコード生成は、実行時コードは可能な限り高速であることを意味しますが、 このためにモジュールが最初に読み込まれるときにコストを支払うことになります。

この読み込み時間は、実行時に毎回読み込みしなければならない コマンドラインスクリプトや「何の変哲もない」CGIスクリプトのように、 起動速度が重要な場合には問題になり得ます。

うろたえる前に、多くの人々がコマンドラインツールやその他の起動時間が重要な コードに Moose を使っていることを知ってください。 起動速度について気にする前にまず Moose を試してみることを勧めます。

Moose はまた他のモジュールに対していくつかの依存があります。 それらのほとんどは小さいスタンドアロンのモジュールで、いくつかは Moose から切り離されたものです。 Moose 自身と、その依存のいくつかは、コンパイラを必要とします。 コンパイラのないシステムにインストールする必要があったり、どんな 依存があっても問題がある場合は、Moose は適切ではないかも知れません。

Moo

Moose を試してみて、これらの理由の一つが Moose を使うのを 妨げているなら、次に Moo を考慮するのを勧めます。 MooMoose の機能のサブセットをより単純なパッケージで実装しています。 実装されているほとんどの機能について、エンドユーザー API は Moose同一 です; つまり Moo から Moose にとても簡単に 切り替えられるということです。

MooMoose のイントロスペクション API を実装しておらず、従って モジュールを読み込むときはしばしばより速いです。 さらに、XS が必要な依存はないので、コンパイラのないマシンでも インストールできます。

Moo の最も切実な機能は Moose との相互運用性です。 Moose のイントロスペクション API を Moo のクラスやロールで使おうと した場合、透過的に Moose のクラスやロールに変換されます。 これにより、Moo を使ったコードと Moose を使ったコードベースに組み込む、 またはその逆を行うことがより容易になります。

例えば、ある Moose のクラスは、extends を使った Moo のクラスの サブクラスになったり、with を使った Moo のロールを消費したりできます。

Moose の作者は、いつの日か Moose が十分改良されることによって Moo が古いものになることを望んでいますが、今のところは Moose に対する 価値のある代替を提供します。

Class::Accessor

Class::AccessorMoose の対極です。 非常に少ない機能しか提供しませんし、セルフホスティングでもありません。

しかし、とても単純で、ピュア Perl で、非コア依存はありません。 また、対応している機能に対する「Moose 風」 API も提供しています。

多くのことはしませんが、それでもクラスを一から書くよりは望ましいです。

以下に Class::Accessor を使った File クラスを示します:

package File;
use Class::Accessor 'antlers';

has path          => ( is => 'ro' );
has content       => ( is => 'ro' );
has last_mod_time => ( is => 'ro' );

sub print_info {
    my $self = shift;

    print "This file is at ", $self->path, "\n";
}

antlers インポートフラグは、属性を Moose 風の文法で定義したいことを Class::Accessor に伝えます。 has に渡せる唯一の引数は is です。 Class::Accessor を選択した場合は、この Moose 風の文法を使うことを勧めます; なぜなら後に Moose に移行しようと決めたときによりスムーズに アップグレードできるからです。

Moose と同様、Class::Accessor はアクセサメソッドとコンストラクタを 生成します。

Class::Tiny

最後に、Class::Tiny があります。 このモジュールはまさにその名前通りです。 これは非常に最小限の API のみを持ち、最近の Perl では全く依存はありません。 それでも、一から独自の OO コードを書くよりも遙かに簡単に使えます。

以下に File クラスをもう一度示します:

package File;
use Class::Tiny qw( path content last_mod_time );

sub print_info {
    my $self = shift;

    print "This file is at ", $self->path, "\n";
}

これだけです!

Class::Tiny では、全てのアクセサは読み書き可能です。 コンストラクタと、定義したアクセサを生成します。

Moose 風の文法の Class::Tiny::Antlers も使えます。

Role::Tiny

前述したように、ロールは継承の代替策を提供しますが、Perl には組み込みの ロール対応はありません。 Moose を使うことを選んだ場合、完全なロール実装が同梱されています。 しかし、その他の推奨 OO モジュールを使う場合、Role::Tiny で ロールを使えます。

Role::Tiny は Moose のロールシステムと同じような機能を提供しますが、 パッケージは遙かに小さいです。 特に、属性宣言には対応していないので、手動で行う必要があります。 それでも、これは有用で、Class::Accessor および Class::Tiny と うまく動作します。

OO System Summary

(OO システムの要約)

以下はここで取り上げた選択肢の簡潔なまとめです:

  • Moose

    Moose は最大限のオプションです。 多くの機能、大きなエコシステム、繁栄しているユーザーベースがあります。 また、Moo も簡単に取り上げました。 MooMoose の簡略版で、Moose があなたのアプリケーションで 動作しないときの妥当な代替案です。

  • Class::Accessor

    Class::Accessor がすることは Moose よりもとても少なく、Moose が おおげさな時にはよい選択肢です。 長い間存在し、よくテストされています。 Class::Accessor から Moose への以降を容易にするための最小限の Moose 互換モードもあります。

  • Class::Tiny

    Class::Tiny は明らかに最小限のオプションです。 依存はなく、学ぶ必要のある文法もほとんどありません。 超最小限環境の場合や詳細について心配することなく素早く何かを作るときには よいオプションです。

  • Role::Tiny

    多重継承について考えているなら Class::Accessor または Class::Tiny と 共に Role::Tiny を使ってください。 Moose を使っているなら、独自のロール実装が同梱されています。

Other OO Systems

(その他の OO システム)

ここで扱ったものの他に、CPAN には文字通り数十のその他の OO 関連の モジュールがあり、他の人のコードを動かすときにはおそらく それらのいくつかを使っているでしょう。

さらに、世の中の多くのコードは全ての OO を「手動で」、単に Perl 組み込みの OO 機能を使って行っています。 もしそのようなコードを保守する必要があるなら、Perl の組み込みの OO が どのように動作するのかを正確に理解するためにperlobj を読むべきです。

CONCLUSION

(まとめ)

既に述べたように、Perl の最小限の OO システムは CPAN での豊富な OO システムを 生み出しました。 今でもこの地金まで降りていってクラスを手で書くこともできる一方、 モダン Perl においてそうする理由は本当はありません。

小さいシステムなら、Class::TinyClass::Accessor の両方は 基本的な定型文の面倒を見る最小限のオブジェクトシステムを提供します。

より大きいプロジェクトなら、Moose はあなたがビジネスロジックの実装に 集中できるような豊富な機能セットを提供します。 多くの機能が必要だけれどもより早いコンパイル時間が必要だったり XS を避けたい場合、MooMoose のよい代替案です。

どの OO システムが適しているかを見るために、Moose, Moo, Class::Accessor, Class::Tiny を試して評価することをお勧めします。