多数の (スタンドアロン) モジュールを使用するモジュールがあり、それらのモジュールはすべて同じ属性 (ローカリゼーション オブジェクトへのハンドル) を持っています。その属性をすべてのクラスに追加する代わりに、その属性を Role に移動しました。これは、すべての最上位クラスによって使用されます。
残念ながら、致命的なエラー「'Role' を再ロードしようとすると中止されました」+「モジュール/ランタイム行 317 でコンパイルに失敗しました」が表示されます。
すべてのクラスでロールを複数回使用していないことを二重および三重にチェックしましたが、問題を攻撃してエラーを見つける方法に少し困惑しています。これは非常に早い段階 (BEGIN の前) に失敗するため、(私が知っている) デバッグする方法があります。
Moo のクラス階層とコンシュームは、基本的に次のようになります (すべてを投稿するにはコードが多すぎますが、それでも多すぎます)。
メインクラス:
SwitchInfo.pm: use Foo::SwitchInfo::DeviceIdent;
SwitchInfo.pm: use Foo::SwitchInfo::Factory;
SwitchInfo.pm: use Foo::SwitchInfo::L10N;
SwitchInfo.pm: use Moo;
役割:
SwitchInfo/Role/L10N.pm: use Moo::Role;
スタンドアロン クラスの最初のレベル:
SwitchInfo/L10N: use base 'Locale::Maketext';
SwitchInfo/StackTable.pm: use Moo;
SwitchInfo/StackTable.pm: with 'Foo::SwitchInfo::Role::L10N';
SwitchInfo/DeviceIdent.pm: use Moo;
SwitchInfo/DeviceIdent.pm: with 'Foo::SwitchInfo::Role::L10N';
SwitchInfo/NameTable.pm: use Moo;
SwitchInfo/NameTable.pm: with 'Foo::SwitchInfo::Role::L10N';
SwitchInfo/Factory.pm: use Moo;
SwitchInfo/Factory.pm: with 'Foo::SwitchInfo::Role::L10N';
SwitchInfo/AliasTable.pm: use Moo;
SwitchInfo/AliasTable.pm: with 'Foo::SwitchInfo::Role::L10N';
SwitchInfo/Domain.pm: use Moo;
SwitchInfo/Driver.pm: use Foo::SwitchInfo::AliasTable;
SwitchInfo/Driver.pm: use Foo::SwitchInfo::Domain;
SwitchInfo/Driver.pm: use Foo::SwitchInfo::NameTable;
SwitchInfo/Driver.pm: use Foo::SwitchInfo::StackTable;
SwitchInfo/Driver.pm: use Moo;
SwitchInfo/Driver.pm: with 'Foo::SwitchInfo::Role::L10N';
サブクラスから第 2 レベルのクラス:
SwitchInfo/Driver/Cisco.pm: use Moo;
SwitchInfo/Driver/Cisco.pm: extends 'Foo::SwitchInfo::Driver';
SwitchInfo/Driver/Extreme.pm: use Foo::SwitchInfo::Domain;
SwitchInfo/Driver/Extreme.pm: use Foo::SwitchInfo::Driver::Extreme::NameTable;
SwitchInfo/Driver/Extreme.pm: use Foo::SwitchInfo::Driver::Extreme::StackTable;
SwitchInfo/Driver/Extreme.pm: use Moo;
SwitchInfo/Driver/Extreme.pm: extends 'Foo::SwitchInfo::Driver';
SwitchInfo/Driver/Extreme/StackTable.pm: use Moo;
SwitchInfo/Driver/Extreme/StackTable.pm: extends 'Foo::SwitchInfo::StackTable';
SwitchInfo/Driver/Extreme/NameTable.pm: use Moo;
SwitchInfo/Driver/Extreme/NameTable.pm: extends 'Foo::SwitchInfo::NameTable';
メインクラスを使用しようとすると、次のエラーが発生します。
$ cat sw.pl
use strict;
use warnings;
use lib './lib';
use Foo::SwitchInfo;
$
$ perl sw.pl
Attempt to reload Foo/SwitchInfo/Role/L10N.pm aborted.
Compilation failed in require at /opt/perl5/lib/perl5/Module/Runtime.pm line 317.
Compilation failed in require at lib/Foo/SwitchInfo.pm line 3.
BEGIN failed--compilation aborted at lib/Foo/SwitchInfo.pm line 3.
Compilation failed in require at sw.pl line 5.
BEGIN failed--compilation aborted at sw.pl line 5.
$
Foo/SwitchInfo.pm の先頭は次のとおりです (行番号付き):
1 package Foo::SwitchInfo;
2
3 use Foo::SwitchInfo::DeviceIdent;
4 use Foo::SwitchInfo::Factory;
5 use Foo::SwitchInfo::L10N;
6 use Types::Standard qw/ ArrayRef InstanceOf Str /;
7 use Type::Utils qw/ as coerce declare from via /;
8
9 use Foo::SNMP;
10
11 use Moo;
12 use namespace::clean;
そして、完全なロールは次のようになります。
package Foo::SwitchInfo::Role::L10N;
use Types::Standard qw/ InstanceOf /;
use Moo::Role;
has l10n => (
is => 'ro',
isa => InstanceOf['Foo::SwitchInfo::L10N'],
handles => qw/ maketext /,
required => 1,
);
1;
小さなテスト スクリプトで、複数のクラスで Role を使用し、それらのクラスを別のクラスで使用しても問題がないことが確認されました。
この長い投稿をまだ読んでいる人がいたら、何か問題を見つけますか? それとも、ロールのこの使用は想定された使用ですか? これは Role を使用する最初の (実際の) 試みであるため、ここで限界を超えている可能性があります。