電子書籍の厳選無料作品が豊富!

Perl初心者です。双方向に値を取り出せる TwoWayMapクラスを作成し、以下の期待値を取得したいのですが、エラーが出てうまく実行できません。原因について、アドバイスをお願いいたします。
(エラーメッセージ)
Can't locate object method "new" via package "TwoWayMap" at samplev2-2.pl line 6.

(期待値)
Apfel
apple
pear


---- TwoWayMap class :ファイル名 samplev2.pl ----------------
package TwoWayMap;
$forward_hash={};
$reverse_hash={};

sub put{
$forward_hash{$_[0]}=$_[1];
$reverse_hash{$_[1]}=$_[0];
}

sub get{
return $forward_hash{$_[0]};
}
sub rev{
return $reverse_hash{$_[0]};
}
---- main ファイル名:samplev2-2.pl------------------------

package main;

use TwoWayMap;
our $e2g = new TwoWayMap;

$e2g->put('apple', 'Apfel');
$e2g->put('pear', 'Birne');

print $e2g->get('apple'), "\n";
print $e2g->rev('Apfel'), "\n";
print $e2g->rev('Birne'), "\n";

A 回答 (4件)

示された samplev2-2.pl 中には、どこにも「samplev2.pl」の読み込み指示がありません。

修正したsamplev2.pl が読み込まれてないだけでしょう。

「use TwoWayMap」した場合、TwoWayMap.pm が読み込まれます。
代わりに「require 'samplev2-2.pl'」としてみてください。

あるいは、とりあえず動作を確認しただけなら、samplev2-2.pl の中に
samplev2.pl の内容をそのまま埋め込んでもいいでしょう。

> ●あと、各メソッド内のforward_hash,reverse_hashなどを$_[0]->として引数から呼び出しているのはなぜでしょうか?


元のコードのままだと、newしたクラスオブジェクトとは無関係に、全体で forward_hash・ reverse_hashを共有することになっていまします。

クラス設計としては、「TwoWayMapクラスのオブジェクト」毎に、二つの連想記憶配列を保持する必要があります。
「クラスオブジェクト」自体は一つの変数ですから、ここに二つの連想記憶配列を保持するために、「連想記憶配列の連想記憶配列」という多段の連想記憶配列として実現してるわけです。
初期化をもうちょっと真面目にやるなら

> sub new {
> my %data;
> $data{forward_hash} = {};
> $data{reverse_hash} = {};
> return bless \%data;
> }
って感じ。

ここで、bless することで、blessされた変数を介したメソッド呼び出しは、
パッケージ指定が不要になり、また暗黙の第1引数が追加されるようになります。これが perl のオブジェクト指向のキモです。

> $e2g->put('apple', 'Apfel');
は、$e2g が package TwoWayMap 内で bless されたものですので、
> TwoWayMap::put($e2g, 'apple', 'Apfel');
と等価になります。

メソッド put は3引数を受け取り、第1引数の変数内の連想記憶配列に、
第2引数・第3引数で指定されたデータを記録しています。
getやrevは2引数を受け取りますので、第1引数内の連想記憶配列から、第2引数で指定されたデータを読み出します。
    • good
    • 0

> ●ありがとうございます。

いただいたコメントをもとに、
> samplev2.plを以下のとおり修正し実行しても、同じエラーが出力さ
> れてしまいます。なぜでしょう?

main側のuseで指定するのはパッケージ名ではなくてファイル名のはず。だから、

package main;
use samplev2;
our $e2g = new TwoWayMap();

としないと、perlはどのファイルがクラス定義をしているのか分からない。

また、クラス定義をする側のファイルの拡張子はplではなく、pmを使うのが普通だったはず。
samplev2.pl → samplev2.pm
    • good
    • 0

このソースでは、名前空間(package名)「TwoWayMap」の下に普通の関数を作っただけで、まったくクラスが作れていません。



クラスの作り方について勉強をやり直してください。キーワードは「bless」でしょうか。
---ここから---
package TwoWayMap;

sub new {
my %data;
return bless \%data;
}

sub put {
$_[0]->{forward_hash}->{$_[1]}=$_[2];
$_[0]->{reverse_hash}->{$_[2]}=$_[1];
}

sub get {
return $_[0]->{forward_hash}->{$_[1]};
}
sub rev {
return $_[0]->{reverse_hash}->{$_[1]};
}
---ここまで---
こんな感じで。

この回答への補足

●ありがとうございます。いただいたコメントをもとに、samplev2.plを以下のとおり修正し実行しても、同じエラーが出力されてしまいます。なぜでしょう?

●あと、各メソッド内のforward_hash,reverse_hashなどを$_[0]->として引数から呼び出しているのはなぜでしょうか?

すみません、いろいろ調べてみてはいるのですが、いまいち理解が進まず質問させていただいております。

(エラー)
Can't locate object method "new" via package "TwoWayMap" at samplev2-2.pl line 6.

(修正後のコード)
#!/usr/bin/perl -w

package TwoWayMap;

sub new {

my %data;
return bless %data;

}

sub put {

$_[0]->{forward_hash}->{$_[1]}=$_[2];
$_[0]->{reverse_hash}->{$_[2]}=$_[1];

}

sub get {

return $_[0]->{forward_hash}->{$_[1]};

}

sub rev {

return $_[0]->{reverse_hash}->{$_[1]};

}

補足日時:2008/06/19 22:55
    • good
    • 0

TwoWayMap パッケージに new というサブルーチンを作ってください.


Perl では「new」という名前に何ら特別な意味はありません.
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!