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