Perl日記

日々の知ったことのメモなどです。Perlは最近やってないです。

Rubyのクラス変数と同じ動きにはClass::Data::Inheritableを使う

まー基本的にはクラス変数使わずにインスタンス変数でなんとかするのですが、メモ。
言語のクラス変数は違うはなし - Perl日記 の続き。

Rubyだと、

class Hoge                                                                                                              
  @@hoge = 'hoge!!!'
end

class Fuga < Hoge
  def hoge
    @@hoge
  end
end

puts Fuga.new.hoge #=> 'hoge!!!'

と継承しても、親クラスのクラス変数が子クラスからでも、修飾なしで参照できるのだが
Perlだと、

use strict;                                                                                                             
use warnings;
use 5.016;
{
  package Hoge;
  our $hoge = 'hoge!!!';
}
{
  package Fuga;
  use parent -norequire, 'Hoge';
  sub new { bless {}, shift }
  sub hoge { $Hoge::hoge } # "Hoge::"をつけないと「Global symbol "$hoge" requires explicit package name」
}

say Fuga->new->hoge; #=> 'hoge!!!'

と、子クラス側から参照するには、"Hoge::"という完全修飾が必要になる(というか、修飾すればどこからでも参照できてしまうが)。


似たようなことをPerlでも実現するには、親クラスでClass::Data::Inheritableを継承する。
http://search.cpan.org/~tmtm/Class-Data-Inheritable-0.08/lib/Class/Data/Inheritable.pm

use strict;
use warnings;
use 5.016;
{
  package Hoge;
  use parent 'Class::Data::Inheritable';
  __PACKAGE__->mk_classdata('Hoge');                                                                                    
  __PACKAGE__->Hoge('hoge!!!');
}
{
  package Fuga;
  use parent -norequire, 'Hoge';
  sub new { bless {}, shift }
  sub hoge { __PACKAGE__->Hoge }
}

say Fuga->new->hoge; #=> 'hoge!!!'


親子で同じ変数を共有しているのは、まあなんか、ちょっと気持ち悪いですけれども。