Perl/ライブラリ・モジュールとオブジェクト指向

Perl4までは、全ての変数は動的で単一のグローバルな名前空間に存在していました。 これは丁度 BASIC と同じ状況で、識別子の衝突の回避がプログラミングの大きなテーマでした。
この問題を解決するためにPerl5では
が導入されました。
グローバル変数は、名前空間の一部とみなされ、「完全修飾形式」( fully qualified form )でアクセスできます。 逆に、レキシカルスコープ変数は、そのレキシカルスコープの一部とみなされ、「完全修飾形式」を持ちません。
Perl の名前空間は「パッケージ」と呼ばれ、package 宣言は変数や非限定動的名の前にどの名前空間を付けるかを決めます。
package 宣言のスコープは宣言に伴うブロック、ブロックを伴わない場合は次のpackage 宣言までです。
ourで宣言された変数は、パッケージ変数です。パッケージ変数はグローバル変数ですが、パッケージに属しています。 our宣言の場所のスコープでしか単純な名前での参照はできませんが、::をつかった完全修飾形式であれば、ourのスコープの外からも参照できます。
Perlも、AWK の BEGIN, END のように特定のタイミングで実行されるコードブロックを定義できます。 特殊コードブロックは、サブルーチンと外観は似ていますが、同じパッケージに2つ以上定義することもできます。まや、直接呼出すことはできません。 5つのどのコードブロックで実行されているかは、${^GLOBAL_PHASE} で参照できます。
BEGINコードブロックは、パースした端から実行されます。 AWKのBEGINと同様です。
UNITCHECKブロックは、それを定義したユニットがコンパイルされた直後に実行されます。 メインプログラムファイルとそれがロードする各モジュールはコンパイル単位であり、文字列評価、正規表現内の (?{ }) 構成を使用してコンパイルされたランタイムコード、do FILE、require FILEの呼び出し、コマンドライン上の-eスイッチの後のコードも同様です。
CHECK コードブロックは、最初の Perl コンパイルフェーズ終了直後、 実行時が開始する直前に、LIFO 順で実行されます。 CHECK コードブロックは Perl コンパイラスイートがプログラムのコンパイル 状態を保存するために使われます。
INIT ブロックは Perl ランタイムが実行を開始する直前に、「先入れ先出し」 (FIFO) 順で実行されます。
ENDコードブロックはできるだけ遅く、perlがプログラムを実行し終わった後、インタープリターが終了する直前に実行されます。
AWKのENDと同様です。
プラグマは、Perl のコンパイル時や実行時の動作に影響を与えるモジュールです。 strict や warnings のように、Perl のコンパイル時や実行時の動作に影響を与えるモジュールです。 Perl 5.10 からは、ユーザーもプラグマを定義できるようになりました。
strictプラグマを有効にすると、宣言済みでないグローバル変数やシンボリックリファレンスなど危険なものの使用を禁止します。それらが出現した時点で例外を発生させ、プログラムを終了します。
use v5.12 以降は strict がディフォルトで有効です。
use モジュール名;とすると、モジュールを使用することができます。対義語はno モジュール名;で、モジュールを不使用にします。
strictプラグマはレキシカルスコープを持つので、このようにブロック内でのみ無効にするということができます。
で、警告の機能を追加できます。
これはperlの -w スイッチと同じで、無意味な演算や未定義の変数の使用、一度も使用されていない変数などに対する警告を有効にします。
use v5.36 以降は、warnings がディフォルトで有効です
警告するだけで、プログラムは続行されます。
ワンライナーや書き捨てのスクリプトを作成する時以外は、strictプラグマと共に常に有効にすることが推奨されます。
perlに標準で同梱されているモジュールのことを標準モジュールといいます。標準モジュール以外のライブラリは、CPANなどから入手します。
CPAN (Comprehensive Perl Archive Network) とは、Perlのライブラリ、モジュール、その他のスクリプトなどを集めた世界的なアーカイブネットワークです。標準モジュールのCPAN.pmでは、シェルからcpanコマンドを使ってCPANのモジュールをインストールするインタフェースを提供しています。
コンストラクターはオブジェクトを返すサブルーチンです。他の多くの言語と同じく名前には new を使います。 他の名前でも、データー構造をクラスに bless し返すサブルーチンは全てコンストラクターです。
組込み関数blessは、コンストラクターの中核で、第一引数(典型的には $self という名前のハッシュ)と、第二引数の(典型的には $class と言う名前のパッケージ)を結びつけたインスタンス(クラスを実体化したオブジェクト)を戻値とします。bless の戻値を使ってメソッドやメンバーを参照します。
オブジェクトの内部構造 $self は、典型的にはハッシュが使われますが、これはハッシュはキー(名前)によって値を取り出すことができるためメンバーを表現するのに適しているためです。 ほかのデーター構造、配列・スカラー・ファイルハンドルなどを内部構造にすることもあります。
クラスの宣言はpackage宣言によって行います。これはライブラリ・モジュールがパッケージを宣言するのと文法的には全く同じです。
メソッドの定義は関数定義と同じsubによって行われます。メソッドは第一引数にオブジェクト(慣習として $self の名前が使われます)が渡されるサブルーチンです。
bless でパッケージと結ぶ付けられたデーター構造にハッシュを使った場合、キーを名前とするメンバー変数として振舞います。
のようにリファレンスで参照します。
Perlでは、パッケージ変数がクラス変数に相当します。
のように、パッケージ内でour宣言された変数(パッケージ変数)はクラス変数として振舞います。
オブジェクトへの最後の参照がなくなると、そのオブジェクトは破棄されます。
このオブジェクトが「破棄」されるサブルーチンがデストラクターです。
デストラクターは、DESTROY と言う名前です(new と異なり名前は DESTROY 固定です)。
DESTROY メソッドはいつでも呼び出すことができるので、 DESTROY メソッドで行う何かによって設定されるかもしれないグローバルなステータス変数をローカル化しなければいけません。 このため、DESTROYのプロローグは下のようなものになります。
オブジェクト指向プログラミングでは、既存のクラスから性質の部分的に異なるクラスを派生させることを継承といいます。
としたとき、Perlは$pt属するクラス(=パッケージ)にabsという名前のメソッドを探しにいきます。 もし見つからなかった場合は、@ISAという特殊な配列に格納されているクラスにabsという名前のメソッドを探しにいきます。
@ISAに基底クラスの名前を入れておくことで、継承を実現することができます。
@ISA の要素数が1の継承は単一継承です。
@ISAに複数のクラス名を列挙する継承が多重継承です。
基底クラス同士が共通のクラスから派生されている継承関係をダイアモンド継承と呼びます。
Perlの多重継承では、2つ以上のコンストラクターを呼出すスマートな方法がないので、片方はコンストラクターを用意せず、メソッドセットとして実装することとなり、実質的に Mix-in になります。
このように、メソッドセットを合成するクラス間の関係を、Mix-inといいます。
SUPER擬似クラス( SUPER pseudo-class )は、常に基底クラスを指しています。基底クラスのメソッドを派生クラス内で呼び出す場合に使用します。
[TODO:多事継承の場合のSUPERの振舞い]
base プラグマを使うと、基底クラスの定義に必要なuseや@ISAの代入から基底クラス内の変数や関数のインポートまでをすべて自動で行うことができます。
このモジュールは、baseからフォークして、溜まっていたゴミを取り除いたものです。
この他にも、Class::Structの様にコンストラクターの自動生成などを行うモジュールなど、クラス定義を補助するユーティリティは幾つかありますが、手早くクラスとクラス階層の有効性を評価するのには便利ですが、クラス設計が完了した時点で、@ISAを直接操作する素朴なコードに書き換えたほうが保守性は向上します。
JavaScript/クラス#包含と継承を、Rubyに移植したコードを、OOPerl に移植しました。