コンストラクタとアクセサ自動生成2
Class::AccessorとClass::Fields
を多重継承してますが、Class::FieldsはメソッドをEXPORTしてるので、
通常にuseするだけでも使えます。
なので、
package MyClass3;
use strict;
use warnings;
use base qw(Class::Accessor);
use Class::Fields;
use CLASS;
use fields qw( name job _mail );
CLASS->mk_accessors(CLASS->show_fields('Public'));
1;
これでもOKです。
多重継承させてません。
で、多重継承をさせずにMix-inさせる手法ですが、
Class::Fieldsでは
以下のようにしてます。
require Exporter;
@ISA = qw(Exporter);
# is_* will push themselves onto @EXPORT
@EXPORT = qw( field_attrib_mask
field_attribs
dump_all_attribs
show_fields
is_public
is_private
is_protected
is_inherited
is_field
);
こうすることで各メソッドをEXPORTしてるわけですが、
Expoter::Liteモジュールをつかえば、
use Expoter::Lite;
@EXPORT = qw( field_attrib_mask
field_attribs
dump_all_attribs
show_fields
is_public
is_private
is_protected
is_inherited
is_field
);
こんな感じで書けます。
で、Exporter::Liteの中身をみたら、
importメソッドをEXPORTしてました。
にゃるほど〜〜〜って感じです。
で、メソッドをEXPORTする時の注意点ですが、
EXPORTするメソッド内でそのメソッドが元々属するクラスの
メソッド(EXPORTされていないメソッド)を呼ぶ場合ですね。
継承ツリーの中にEXPORTされていないメソッドは見つけることができないので、
(継承してないから当然ですね)
例外が発生します。
例えばこんなのかな。
電話をかけて話す猫がいたとします。
Telクラスで電話をかけて、
Speekクラスでしゃべります。
こんなサンプルでよいのか激しく疑問w
Telクラスは
telメソッドをエクスポートし、
Speekクラスは
speekメソッドをエクスポートしてます。
./neko.pl
#! /usr/bin/perl
use strict;
use warnings;
use Neko;
my $n = Neko->new;
$n->tel;
$n->speek;
./Neko.pm
package Neko;
use strict;
use warnings;
use Speek;
use Tel;
sub new {
my($class,$self)=(shift,{@_});
bless($self,$class);
$self;
}
1;
./Tel.pm
package Tel;
use strict;
use warnings;
use vars qw(@ISA @EXPORT);
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(
tel
);
sub new {
my($class,$self)=(shift,{@_});
bless($self,$class);
$self;
}
sub tel {
my $self = shift;
my $no = shift->get_phone_no;
print $no;
}
sub get_phone_no {
my $self = shift;
return "090-000-0000";
}
1;
./Speek.pm
package Speek;
use strict;
use warnings;
use vars qw(@ISA @EXPORT);
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(
speek
);
sub new {
my($class,$self)=(shift,{@_});
bless($self,$class);
$self;
}
sub speek {
my $self = shift;
my $no = $self->get_word;
print $no;
}
sub get_word {
my $self = shift;
return "Hello";
}
1;
ここでの注目は
Telクラスのget_phone_noメソッドと
Speekクラスのget_wordメソッドです。
こいつらはEXPORTされてません。
この状態でneko.plを実行すると。
Can't locate object method "get_phone_no" via package "Neko" at Tel.pm line 21.
と例外が発生します。
Neko.pmからはEXPORTされていないget_phone_noは見えないですからね。
で、どうするかというと、
Tel.pmのtelメソッドを以下のように修正します。
sub tel {
my $self = shift;
my $no = get_phone_no($self);
print $no;
}
すると次は
Can't locate object method "get_word" via package "Neko" at Speek.pm line 22.
こんな例外が発生します。
Speekクラスのget_wordメソッドもEXPORTしてないですからね。
で、こんな感じで修正します。
sub speek {
my $self = shift;
my $no = get_word($self);
print $no;
}
するとうごきます。
で、
get_phone_no($self);
こんなのがいやだと。
なんでOOPやってるのに関数チックな呼び出しをするのかと
じゃあこうしませう。
sub tel {
my $self = shift;
my $no = __PACKAGE__->get_phone_no;
print $no;
}
パッケージ修飾でメソッドを呼び出します。
ちょっと長くなりましたが、以上こんな感じでいかがでしょうか?