blessは、任意のリファレンスをパッケージに結びつける関数です。 パッケージと結びつけられたリファレンスをオブジェクトと呼びます。
次のコードは、ハッシュリファレンスの$pointとSome::Pointパッケージを結びつけています。 他の言い方をすれば、ハッシュリファレンスの$pointをSome::Pointパッケージがblessしています。
my $point = { x => 3, y => 4 }; bless $point, 'Some::Point'; package Some::Point { sub radius { my $point = shift; return sqrt($point->{x} ** 2 + $point->{y}**2) } }
リファレンスとパッケージを結びつけると、関数の呼び出しに関して特別対応されます。
例を用いて、順に説明します。
上記のコードの通り、Some::Pointパッケージには、三平方の定理で半径を求めるradius関数が定義されています。
このradius関数は、Some::Point::radius(..)
のようにパッケージ名::関数名(..)
と書けば、呼び出せます。
my $point = { x => 5, y => 12 }; Some::Point::radius($point) # => 13
そして、肝心の特別対応ですが、ハッシュリファレンスの$pointを、Some::Pointパッケージでblessした時、
$point->radius()
と書けば、Some::Point::radius($object)
と同等の呼び出しになります。
my $point = { x => 5, y => 12 }; bless $point, 'Some::Point'; $point->radius(); # Some::Point::radius($object) と同等
つまり、blessすることで、オブジェクトに紐づいたパッケージの関数呼び出しができます。この呼び出し方をメソッド呼び出しと言います。
まとめ
blessには、任意のリファレンスをパッケージに結びつけて、メソッド呼び出し構文を使えるようにする効果があります。
おまけ
補足1:
$point->some_method
のように、Some::Pointパッケージに定義されていない関数が指定された場合、親のパッケージにその関数がないか探す効果もあります。
bless関数の説明しなかった効果は、これくらいです。
補足2:
結びつけられるリファレンスは、どんなリファレンスでも良いです。 ハッシュリファレンスがよく使われますが、配列リファレンス、スカラリファレンス、コードリファレンスが使えます。 例えば、このSome::Pointを、次のように書き換えたら、メモリ効率、パフォーマンスの利点があるでしょう。
my $point = [3,4]; bless $point, 'Some::Point'; package Some::Point { sub radius { my $point = shift; return sqrt($point->[0] ** 2 + $point->[1]**2) } }
補足3:
慣習的に、blessする関数の名前をnewと名付けることが多いです。
package Some::Point { sub new { my ($class, $x, $y) = @_; return bless [$x, $y] => $class; } sub radius { my ($self) = @_; return sqrt($self->[0] ** 2 + $self->[1]**2); } } my $point = Some::Point->new(3,4); $point->radius; # => 5
補足4:
ざっくりした咀嚼をすると、「パッケージにはふるまいが定義され、リファレンスは状態を持ち、 blessすると、ふるまいと状態を結びつけたオブジェクトができる」と考えられます。
補足5:
v5.38からperlのコアにクラスを作成するためのclass featureが追加されました。より現代的なオブジェクト指向プログラミングをする場合、こちらを利用する方が良いと思います。もし、5.38が利用できない場合は、v5.14以上であれば、Feature::Compat::Classを利用して同等の機能を利用できます。