先ず、カレントディレクトリがworkだとして、そこにMyModディレクトリを用意します。
以下に3つのファイルのうち、Animal.pmとBird.pmをMyModに移動、カレントディレクトリにはMain.plだけ残します。
[Animal.pm]
package Animal;
use Carp qw/croak/;
sub new{
my $pkg = shift;
bless {
name => shift || croak 'need a name'
}, $pkg;
}
1;
[Bird.pm]
package Bird;
use base qw/Animal/;
sub fly{
print "flay away!\n";
}
1;
[Main.pl]
package main;
use MyMod::Bird;
my $bird = Bird -> new('Pepe');
$bird -> fly;
この状態から、Main.plを実行すると、、、Can't locate MyMod/Bird.pm in @INC..とエラーが返ってきます。
何故でしょうか?解決策をご教授ください。
最小の変更としたいのであればBird.pmを下記の様にしてみてください。
package Bird; use MyMod::Animal; use base qw/Animal/; ~
@INCに"."(ピリオド)は含まれていますよね?
そのエラーの前に
Base class package "Animal" is empty. (Perhaps you need to 'use' the module which defines that package first, or make that module available in @INC (@INC contains:~).
のようなエラーがありませんか?
モジュールは@INCにあるパスの位置から探しますが、そこに"."(ピリオド)があるためカレントディレクトリからは探します。しかし、モジュールやソースコードの位置を基準にしては探しません。
なので、MyMod/Bird.pmで「use base qw/Animal/;」としてもカレントディレクトリ他にはないので失敗します。すると「use MyMod::Bird;」が失敗して「Can't locate」のエラーも出たような気がします。
なので一度「use MyMod::Animal;」をして(Animalモジュールではなく)MyMod::Animalモジュールを読み込み(MyMod::Animalパッケージではなく)Animalパッケージを定義すればエラーにならなかったと思います。
ただ、通常はモジュール名とパッケージ名を合わせますので、Craftworksさんのも含め、すべてのファイルのすべての「Animal」と「Bird」を変更するか、下記の様にしてMain.plでMyModディレクトリを@INCに含めます。
use lib './MyMod' package main; use Bird; ~
package Bird;
ではなく、
package MyMod::Bird;
としてください。
簡潔な回答をありがとうございました。TransFreeBSDさんの回答とあわせて、問題を解決することができました。
最小の変更としたいのであればBird.pmを下記の様にしてみてください。
package Bird; use MyMod::Animal; use base qw/Animal/; ~
@INCに"."(ピリオド)は含まれていますよね?
そのエラーの前に
Base class package "Animal" is empty. (Perhaps you need to 'use' the module which defines that package first, or make that module available in @INC (@INC contains:~).
のようなエラーがありませんか?
モジュールは@INCにあるパスの位置から探しますが、そこに"."(ピリオド)があるためカレントディレクトリからは探します。しかし、モジュールやソースコードの位置を基準にしては探しません。
なので、MyMod/Bird.pmで「use base qw/Animal/;」としてもカレントディレクトリ他にはないので失敗します。すると「use MyMod::Bird;」が失敗して「Can't locate」のエラーも出たような気がします。
なので一度「use MyMod::Animal;」をして(Animalモジュールではなく)MyMod::Animalモジュールを読み込み(MyMod::Animalパッケージではなく)Animalパッケージを定義すればエラーにならなかったと思います。
ただ、通常はモジュール名とパッケージ名を合わせますので、Craftworksさんのも含め、すべてのファイルのすべての「Animal」と「Bird」を変更するか、下記の様にしてMain.plでMyModディレクトリを@INCに含めます。
use lib './MyMod' package main; use Bird; ~
理屈まで丁寧にご説明いただき、ありがとうございました。全てのAnimal, BirdにExtend::を付加することで解決できました。
理屈まで丁寧にご説明いただき、ありがとうございました。全てのAnimal, BirdにExtend::を付加することで解決できました。
2012/01/28 16:33:07