aメソッドを含むモジュールがありb、それらをエクスポートしたい場合は、次のようにします。
use Exporter;
our @ISA = qw (Exporter);
our @EXPORT = qw (a b);
私が理解していないのは、この行が何をしているのかです:
our @ISA = qw (Exporter);do?
aメソッドを含むモジュールがありb、それらをエクスポートしたい場合は、次のようにします。
use Exporter;
our @ISA = qw (Exporter);
our @EXPORT = qw (a b);
私が理解していないのは、この行が何をしているのかです:
our @ISA = qw (Exporter);do?
ここでオブジェクト指向を考えてみましょう。
Exporter は単なるモジュールではなく、クラスと考えてください。「My module is a sub-class of Exporter」のISAように「Is a」を意味すると考えてください。
あなたがしているのは、モジュールを Exporter クラスのサブクラスとして宣言することです。つまりimport、便利な Exporter クラスのメソッドを使用できるということです。
Exporter が何をしているかを実際に説明するには、Perl が名前空間を使用することを理解する必要があります。プログラムにという変数1$totalがあり、使用しているモジュールもそうであると想像してください。あなた$totalの変数はモジュールの変数に干渉し$totalます。
これを防ぐために、Perl は名前空間を使用します。プログラムは、デフォルトの名前空間で動作しますmain。モジュールは、関数を使用して新しい名前空間packageを宣言します。これで、あなたとあなたのモジュールの両方が という変数を安全に使用できます。あなたのプログラムでは、それは実際には $Package::Name::total $File::Find::name $File::Find::dir File::Find` です。$total$main::total. If you want to use something from one _namespace_ in another, you can prepend the _namespace_ on it. Think of theandvariables you have when you use
エクスポーターのimportメソッドが行うことは、サブルーチン (および必要に応じて変数) を名前空間から現在の名前空間にコピーすることです。サブルーチンをメインの名前空間にコピーするFile::Copy機能なしでモジュールを使用することを想像してください。引き続き使用できますが、名前空間の名前を付ける必要があります。copy
use File::Copy;
...
File::Copy::copy( $from_file, $to_file );
@EXPORTExporter (および import メソッド) のおかげで、packages配列に入れたサブルーチンはすべて現在の名前空間にコピーされます。sしたがって、次のように File::Copy copy` サブルーチンにアクセスできます。
use File::Copy;
...
copy ( $from_file, $to_file );
ourこれが、これらすべての変数を asおよび notとして宣言する必要がある理由でもありますmy。my変数はレキシカル スコープであり、宣言されている場所以外からアクセスすることはできません。パッケージ変数 ( など$File::Find::name) を使用できます。および配列Exporterを見つけるには、これらがパッケージ変数である必要があります。@EXPORT@EXPORT_OK
さて、関数をエクスポートすることが望まれます...
私たちが知っていて愛用している最も古いモジュールは、サブルーチンを意のままにエクスポートします。File::Copy、File::Path、File::Find を使用すると、それらのサブルーチンにすぐにアクセスできます。@EXPORTこれは、サブルーチンを配列に入れるためです。これは、これらの機能をすぐに利用できるようにするため、一時は望ましいと考えられていました。
次のような新しいモジュールでFile::Tempは、インポートするサブルーチンを宣言する必要があります。
use File::Temp qw(tempdir);
...
my $temp_dir = tempdir;
これがないと機能qw(tempdir)が使えませんtempdir。
これは礼儀正しいと見なされます。モジュールは、関数をインポートする許可を求めています。これは、サブルーチンを に入れることによって行われ@EXPORT_OKます。これらは、要求があった場合にのみエクスポートされます。
すべてをインポートする必要はなく、必要なものだけをインポートする必要があるため、これは優れています。そして、これらの関数が定義されている場所を文書化しています。
オブジェクト指向モジュールは何もエクスポートしないため、エクスポーターを使用する必要はありません。Exporter を使用するモジュールを作成してから長い時間が経ちました。
-- 1ここではパッケージ変数について話しています。パッケージ変数はどこにでも表示されます。
Exporterパッケージ内でメソッドが見つからない場合、モジュール内でメソッドを探すように Perl に指示します。継承したい通常のメソッドExporterはそのimportメソッドであり、モジュールのエクスポートされたシンボルを呼び出し元のパッケージにコピーする作業が行われる場所です。
からperlobj:
各パッケージには、 と呼ばれる特別な配列が含まれています
@ISA。配列には、そのクラスの親クラスのリストが含まれています(@ISA存在する場合)。この配列は、Perl がメソッド解決を行うときに調べられますが、これについては後で説明します。
たとえば、Perl が存在しないサブルーチンを呼び出そうとするため、これはエラーですFoo::some_method。
sub Bar::some_method { 42 }
my $obj = bless {}, 'Foo';
$obj->some_method;
パッケージ内の@ISA変数は、Perl に他のパッケージ内のメソッドを探すように指示するため、このコードは機能してBar::some_methodメソッドを呼び出します。
sub Bar::some_method { 42 }
my $obj = bless {}, 'Foo';
@Foo::ISA = qw(Bar);
$obj->some_method;
これの実用的なアプリケーションは継承です。
@ISAamon が言及しているように、直接設定する必要はめったにありません。parentプラグマ (および、現在推奨されていない古いプラグマ)は、base継承関係を宣言し、この変数を設定します。
@ISAパッケージ変数は、クラス間の継承を指定するために使用されます。この変数を自分で操作することはお勧めできません。別のクラスから継承したい場合は、
use parent 'Parent::Class';
または v10.1 より前の場合:
use base 'Parent::Class';
この特定のケースでは、継承Exporterによってimportメソッドが使用可能になります。あなたのコードは次のように書き直すことができます。
use parent 'Exporter';
our @EXPORT = qw/a b/;
このimportメソッドは、モジュールがused のときに自動的に呼び出され、シンボルを using パッケージにエクスポートする場合があります。
@ISA手動で使用するのが悪い理由:
に割り当てないでください@ISA: 他のモジュールがすでにエントリを追加している可能性があります。これはそれらを上書きします。したがって、push @ISA, "Some::Class".
実行中の変更は避けてください@ISA。モジュールをそこで制限なく使用できるように、継承関係をできるだけ早く (解析中または最初のコンパイル後に) 指定することをお勧めします。BEGIN次のようにorCHECKブロックでラップできます
BEGIN {
push @ISA, "Some::Class";
}
継承 via をparent使用すると、これがはるかに簡単になります。parentまだロードされていない場合は、要求されたモジュールもコンパイルしますuse Some::Class。