7

aメソッドを含むモジュールがありb、それらをエクスポートしたい場合は、次のようにします。

use Exporter;  
our @ISA = qw (Exporter);  
our @EXPORT = qw (a b);  

私が理解していないのは、この行が何をしているのかです:
our @ISA = qw (Exporter);do?

4

4 に答える 4

8

ここでオブジェクト指向を考えてみましょう。

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として宣言する必要がある理由でもありますmymy変数はレキシカル スコープであり、宣言されている場所以外からアクセスすることはできません。パッケージ変数 ( など$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ここではパッケージ変数について話しています。パッケージ変数はどこにでも表示されます。

于 2013-07-29T20:27:48.120 に答える
3

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継承関係を宣言し、この変数を設定します。

于 2013-07-29T19:13:14.867 に答える
3

@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

于 2013-07-29T19:00:47.597 に答える