第27回 blessの使い方にもっと精通しよう

では、Perlオブジェクト指向をするのに必要な bless の知識に話を戻していこう。


まず、
第24回 別のパッケージの関数を呼び出すもう1つの方法 bless - bingo_nakanishiの他言語出身者のためのPerl入門
で、扱ったblessの内容をまとめておく。

blessとは

リファレンスを受け取り、リファレンスを返す

blessに与えられたものは、パッケージの関数が呼べる



ここから新しい知識

さて、ここから新しい知識を増やしていこう。
blessの第2引数は、省略可能なのである。
省略されると bless が書かれているパッケージのパッケージ名が補われる。

use strict;

sub h {
  print '呼ばれた', "\n";
}

my $c;
$c = bless \$c; # 第2引数を省略

$c->h();

結果:

呼ばれた

ちょ、ちょっと待ってくれ。どこにも、
package と書かれている部分がないように思えるが!!

main パッケージ

いままで、パッケージ(名前空間)を考えなかった段階では、普通にpackage文など書かずにソースを書いてきている。

use strict;

sub f {
 print 'こんにちは', "\n";
}

f();

結果:

こんにちは


実は何も書かなければ そこは、mainと呼ばれるパッケージ(名前空間)なのだ。
次のソースを試してほしい。

use strict;

sub f {
 print 'こんにちは', "\n";
}

main::f();

結果:

こんにちは

よって先ほどの例は、

use strict;

sub h {
  print '呼ばれた', "\n";
}

my $c;
$c = bless \$c, 'main'; # 第2引数をちゃんと書いた

$c->h();

このソースと同じなのである。
これが、「bless が書かれているパッケージのパッケージ名が補われる」ということである。


ただ bless をするだけの関数を作ってみる

ここで、ただblessするだけの関数を作ってみよう。
そんなことをしてなにがうれしいのか? と思うかもしれないが、
とりあえず 作ってみよう。

use strict;

sub hoge {
  my $d;
  bless \$d;  # 関数の最後なので、この式の返り値(blessの結果)が この関数の戻り値となる
}

sub f {
  print 'こんにちは', "\n";
}

my $c = hoge(); # hoge関数は内部でblessを呼んでいる
$c->f();

結果:

こんにちは


ここで、もう一歩おし進めて、引数をもらえるようにしてみよう。

blessするだけの関数に引数を与える

use strict;
use Data::Dumper;

sub hoge {
  my $d = shift;
  bless $d;
}

sub f {
  print 'こんにちは', "\n";
}

my $c = 1;
my $e = hoge(\$c);

$e->f();
print $$e, "\n";

結果:

こんにちは
1

次回は

さて、今回は、
ただblessするだけの関数をmainパッケージの中に書いたが、
次回は、これを別のパッケージに書いてみることにする。


それでは また〜











# ここからは、私自身がこの記事を書いていて出会った現象
こうすると、

use strict;
use Data::Dumper;

sub hoge {
  my $d = shift;
  bless $d;
}

sub f {
  print 'こんにちは', "\n";
}

my $c = 1;
$c = hoge(\$c);

$c->f();
print $$c, "\n";

結果:

こんにちは
main=REF(0x80177c)

こう表示されてしまった 理屈がわからん......