use strictと@ISA
大域変数を使用禁止にするでも書きましたが,use strictを指定すると,大域変数を使用禁止にできます.これは,スーパークラスを登録する@ISAにも影響を与えます.
まず,このプログラムは動きます.
#!/usr/bin/perl -w
package Foo;
sub new{
return bless {},$_[0];
}
sub print{
print "Hello world.\n";
}
package Bar;
@ISA=('Foo');
sub new{
return $_[0]->SUPER::new; #スーパークラスのコンストラクタを使う.
}
package main;
my $bar=Bar->new; #クラスBarのインスタンスを作って
$bar->print; #スーパークラスFooのメソッドを使う.
実行結果はこうなります.
$ sam.pl sam.pl Hello world.
同じプログラムにuse strictを指定します.
#!/usr/bin/perl -w use strict; #use strictを指定 package Foo; sub new{ return bless {},$_[0]; } sub print{ print "Hello world.\n"; } package Bar; @ISA=('Foo'); sub new{ return $_[0]->SUPER::new; #スーパークラスのコンストラクタを使う. } package main; my $bar=Bar->new; #クラスBarのインスタンスを作って $bar->print; #スーパークラスFooのメソッドを使う.
実行結果はこうなります.
$ sam.pl sam.pl Global symbol "@ISA" requires explicit package name at ./sam.pl line 13. Execution of ./sam.pl aborted due to compilation errors.
エラーメッセージに従い,@ISAにパッケージ名をつけると動きます.
#!/usr/bin/perl -w use strict; #use strictを指定 package Foo; sub new{ return bless {},$_[0]; } sub print{ print "Hello world.\n"; } package Bar; @Bar::ISA=('Foo'); パッケージ名を指定 sub new{ return $_[0]->SUPER::new; #スーパークラスのコンストラクタを使う. } package main; my $bar=Bar->new; #クラスBarのインスタンスを作って $bar->print; #スーパークラスFooのメソッドを使う.
実行結果
$ sam.pl sam.pl Hello world.
@ISAをパッケージの局所変数にすると,スーパークラスがわからないようです.
#!/usr/bin/perl -w use strict; #use strictを指定 package Foo; sub new{ return bless {},$_[0]; } sub print{ print "Hello world.\n"; } package Bar; my @ISA=('Foo'); @ISAをパッケージの局所変数にする sub new{ return $_[0]->SUPER::new; #スーパークラスのコンストラクタを使う. } package main; my $bar=Bar->new; #クラスBarのインスタンスを作って $bar->print; #スーパークラスFooのメソッドを使う.
実行結果
$ sam.pl sam.pl Can't locate object method "new" via package "Bar" (perhaps you forgot to load "Bar"?) at ./sam.pl line 15.
@ISAをパッケージの局所変数にした場合のこのエラーは,サブクラスの中でスーパークラスのメソッドを使った場合に表面化します.サブクラスの中でスーパークラスのメソッドを使っていない場合には,このエラーは発生しません.
#!/usr/bin/perl -w use strict; #use strictを指定 package Foo; sub new{ return bless {},$_[0]; } sub print{ print "Hello world.\n"; } package Bar; my @ISA=('Foo'); @ISAをパッケージの局所変数にする sub new{ return bless {},$_[0];#スーパークラスのコンストラクタを使わない. } sub print{ print "Hello world.\n"; サブクラスにも同じメソッドがある } package main; my $bar=Bar->new; #クラスBarのインスタンスを作って $bar->print; #クラスBarのメソッドを使う.
このプログラムは動きます.
$ sam.pl sam.pl Hello world.
サブクラス内でSUPERを使用して明示的にスーパークラスのメソッドを使っていなくても,サブクラスからスーパークラスへメソッドを検索する過程でエラーになることがあります.
#!/usr/bin/perl -w use strict; #use strictを指定 package Foo; sub new{ return bless {},$_[0]; } sub print{ print "Hello world.\n"; } package Bar; my @ISA=('Foo'); @ISAをパッケージの局所変数にする sub new{ return bless {},$_[0];#スーパークラスのコンストラクタを使わない. } package main; my $bar=Bar->new; #クラスBarのインスタンスを作って $bar->print; #スーパークラスFooのメソッドを使う.
実行結果はこうなります.
$ sam.pl sam.pl Can't locate object method "print" via package "Bar" (perhaps you forgot to load "Bar"?) at ./sam.pl line 20.
上記プログラムの場合,クラスBarにメソッドprintがなかったため,スーパークラスFooのメソッドprintを探そうとしますが,@ISAがパッケージBarの局所変数であったためスーパークラスFooが見つけられなかったようです.推測です.
動作環境はWindows2000 Professional+SP2,cygwin1.3.9,perl5.6.1です.