人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

Perlの継承について質問させてください。

先ず、カレントディレクトリが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..とエラーが返ってきます。
何故でしょうか?解決策をご教授ください。

●質問者: hiirosato
●カテゴリ:コンピュータ ウェブ制作
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● Craftworks
package Bird;

ではなく、

package MyMod::Bird;

としてください。


hiirosatoさんのコメント
簡潔な回答をありがとうございました。TransFreeBSDさんの回答とあわせて、問題を解決することができました。

2 ● 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;
?

hiirosatoさんのコメント
理屈まで丁寧にご説明いただき、ありがとうございました。全てのAnimal, BirdにExtend::を付加することで解決できました。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ