オブジェクトを生成する
bless
はオブジェクト指向プログラミングにおけるクラスを生成する際に使われます。
もう少し正確に言うと、Perl における単なるパッケージをクラスかのように見せ、その中で定義した
ハッシュ参照をそのクラスのインスタンスのようにしてくれます。
具体的なクラスの作り方と使い方は後述しますが、まずは bless
の仕様を見てみましょう。
bless
は、REF の参照先をパッケージ内のオブジェクトとしてマークするよう Perl に指示します。
特別な理由ない限り、2 つの引数を取る bless
のほうが推奨されます。
bless $ref, $package;
2 つの引数を取る場合、オブジェクトを第二引数に指定したパッケージに加えます。
main
パッケージに bless するbless $ref, "";
第二引数が空文字列なら、bless
は オブジェクトを main
パッケージに追加します。
bless $ref;
bless
が第二引数なしに使われた場合、そのオブジェクトは現在のパッケージの中で生成されます。
派生クラスが bless
を実行してメソッドを継承する可能性があるなら、必ず第二引数を指定するべきです。
1 つの引数しか取らない bless
は、潜在的なバグの原因になる可能性があるため、非推奨となっています。
CLASSNAME は常に大文字と小文字を組み合わせた名前にするべきです。 それは、すべて大文字、または、すべて小文字の名前は、Perl においては、それぞれ組み込みの型やプラグマとして使われることを意味するからです。 混乱を避けるためにも、すべて大文字、または、すべて小文字のパッケージ名の生成は避けてください。
また、0
をクラス名にしないでください。
これは、参照が bless
に失敗したのかを見るために ref
の結果をチェックした際に問題となります。なぜなら "0" が返ってしまうからです。
以上、bless
の仕様を説明しましたが、これではオブジェクト指向プログラミングのイメージがわきません。
bless
を使って簡単なクラスを作ってみましょう。
Perl におけるクラスは単なるパッケージのことです。
ここでは MyClass
という名前のパッケージを MyClass.pm
というファイル名で保存します。
package MyClass;
sub new {
my ( $class, %args ) = @_;
my $self = { name => $args{name} };
return bless $self, $class;
}
sub greet {
my($self) = @_;
print "Hi, my name is " . $self->{name} . "\n";
}
1;
ここではパッケージ名を MyClass
としていますが、これがクラス名になります。
サブルーチン new
がいわゆるコンストラクタのような存在になります。
Perl の仕組み上、コンストラクタとなるサブルーチンの名前は new
でなくても構いませんが、
分かりやすさを考えると new
としておくのが良いでしょう。
サブルーチン new
には 2 つの引数が引き渡されます。
一つ目はクラス名です。この場合は MyClass
がセットされます。
二つ目は new
が呼び出された際に引き渡されたパラメータです。
サブルーチン new
の中ではハッシュ参照 $self にパラメータの値をセットしています。
このハッシュ参照を bless
することで、クラス名 MyClass
のインスタンスが生成されます。
bless
によって生成されたインスタンスは $self
そのものですが、このインスタンスを通して、
$self にセットされたフィールドやメソッドにアクセスできるようになります。
では、この MyClass
を使うコードを見てみましょう。
require './MyClass.pm';
my $myclass = MyClass->new( name => 'Taro' );
$myclass->greet(); # "Hi, my name is Taro"
このように、bless
は、もともとオブジェクト指向プログラミング言語でない Perl に、
単なるパッケージをクラスとして扱えるようにすることで、Perl でもオブジェクト指向プログラミングができるようにします。
なお、Perl v5.38 から実験的に class 構文が導入されました。
将来的にはパッケージを bless
するのではなく、
Perl コアに組み込まれた class 構文を使うことが主流になるのかもしれません。
Perl の class 構文の詳細については記事「Perl に class 構文がやってきた」
をご覧ください。