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です.