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 the
and
variables you have when you use
エクスポーターのimport
メソッドが行うことは、サブルーチン (および必要に応じて変数) を名前空間から現在の名前空間にコピーすることです。サブルーチンをメインの名前空間にコピーするFile::Copy
機能なしでモジュールを使用することを想像してください。引き続き使用できますが、名前空間の名前を付ける必要があります。copy
use File::Copy;
...
File::Copy::copy( $from_file, $to_file );
@EXPORT
Exporter (および 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;
これの実用的なアプリケーションは継承です。
@ISA
amon が言及しているように、直接設定する必要はめったにありません。parent
プラグマ (および、現在推奨されていない古いプラグマ)は、base
継承関係を宣言し、この変数を設定します。
@ISA
パッケージ変数は、クラス間の継承を指定するために使用されます。この変数を自分で操作することはお勧めできません。別のクラスから継承したい場合は、
use parent 'Parent::Class';
または v10.1 より前の場合:
use base 'Parent::Class';
この特定のケースでは、継承Exporter
によってimport
メソッドが使用可能になります。あなたのコードは次のように書き直すことができます。
use parent 'Exporter';
our @EXPORT = qw/a b/;
このimport
メソッドは、モジュールがuse
d のときに自動的に呼び出され、シンボルを using パッケージにエクスポートする場合があります。
@ISA
手動で使用するのが悪い理由:
に割り当てないでください@ISA
: 他のモジュールがすでにエントリを追加している可能性があります。これはそれらを上書きします。したがって、push @ISA, "Some::Class"
.
実行中の変更は避けてください@ISA
。モジュールをそこで制限なく使用できるように、継承関係をできるだけ早く (解析中または最初のコンパイル後に) 指定することをお勧めします。BEGIN
次のようにorCHECK
ブロックでラップできます
BEGIN {
push @ISA, "Some::Class";
}
継承 via をparent
使用すると、これがはるかに簡単になります。parent
まだロードされていない場合は、要求されたモジュールもコンパイルしますuse Some::Class
。