19
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

blessは破壊的メソッドである罠

Last updated at Posted at 2013-06-07

##結論

blessは、オブジェクトを返すんじゃなくて、
受け取ったリファレンス自体をオブジェクト化して返す
→blessは破壊的メソッド。

これを知らないと、以下の罠にはまります。

##追記(2013/11/19)

package Class1;
sub new{
my ($class, %args )  = @_;
  bless +{
    hoge => 'initial value',
    %args,
  }, $class;
}

Class1->new( hoge => 1)

cpanを見ると、上記のように書くのが一般的なようです。
そもそも参照で渡すな、って話でした。

##例

package Class1;
sub new{
my ($class, $args )  = @_;
  bless $args, $class;
}

package Class2;
sub new{
my ($class, $args )  = @_;
  bless $args, $class;
}

と適当なクラスを定義します。

my $args = {hoge => 'hoge'};

my $obj1 = Class1->new($args);
my $obj2 = Class2->new($args);

print ref $args; # => Class2
print ref $obj1; # => Class2

$obj1がClass2なんだぜこれ…
$argsもちゃっかりオブジェクトになってるし…

対策

$obj1をきちんとClass1にするためには、
以下のうちどれかをすればいいです。

  • 無名ハッシュで渡す
  • そのままblessせずに、無名ハッシュをblessする
  • bless Clone::clone($args), $class とする

なお、unblessも破壊的です。

19
20
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?