2013-07-29 43 views
6

私は方法abでモジュールを持っていると私はそれらをエクスポートする場合:
our @ISA = qw (Exporter);ください:私は理解していない何Perlで@ISAとは何ですか?

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

は、この行が何をしているのですか?

+1

'perldoc perlobj'と' perldoc perltoot'を参照してください。 –

+2

メソッドをエクスポートするのは意味がありません。あなたは "subs"を意味しますか? – ikegami

答えて

3

@ISAパッケージ変数は、クラス間の継承を指定するために使用されます。この変数を自分で操作するのはお勧めできません。あなたが別のクラスから継承したい場合は、

use parent 'Parent::Class'; 

や前バージョン10.1を実行します。

use base 'Parent::Class'; 

をこの特定のケースでは、Exporterから継承するimport方法が利用できるようになります。あなたのコードは、次のように書き直すことができます。

use parent 'Exporter'; 
our @EXPORT = qw/a b/; 

import方法は、お使いのモジュールがuse dとしたときに自動的に呼び出され、そして使用してパッケージにシンボルをエクスポートすることがあります。


@ISAを使用して、なぜ手動悪いです:

  • @ISAに割り当てないでください:他のモジュールがすでにそれにエントリを追加したこと。これはそれらを上書きします。したがって、push @ISA, "Some::Class"

  • 実行時に@ISAを変更しないでください。可能な限り早く(解析中または初期コンパイル後に)継承関係を指定する方がよいので、モジュールを制限なしにそこで使用することができます。 parent経由

    BEGIN { 
        push @ISA, "Some::Class"; 
    } 
    

継承は、これは非常に簡単になりますようにあなたは、BEGINまたはCHECKブロックでそれを包むことができます。 parentは、まだロードされていない場合でも要求されたモジュールをコンパイルします。use Some::Classは不要です。

+0

しかし、なぜ私はそれを明示的に書く必要がありますか?その後、私はそれを使用しません – Jim

+0

@ジム私は理解していません。 Exporterモジュールでは、パッケージが '使用されているときには、シンボルをエクスポートすることができます。これは 'import'メソッドで実装されています。あなたは自分で書くことができます(エラーが起こりやすい)か、 "Exporter"から多彩な実装を継承することができます。継承は内部的に '@ ISA'配列で表されます。 – amon

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; 

実用的なアプリケーションは継承です。

amonに言及すると、@ISAを直接設定する必要はほとんどありません。 parentプラグマ(および古くなった、今は落ちたbaseプラグマ)は継承関係を宣言し、この変数を設定します。

11

配列は、クラスFooが継承するクラスを保持するグローバル変数です。

通常、@ISAを直接操作しないでください。そうすることは、古いPerlコードを見ている可能性があるという印です。

あなたが継承関係を宣言したい場合は、それを行うには良い方法はあなたのために舞台裏で@ISAを微調整しても、他のいくつかの有用なものをし

use parent 'Exporter'; 

です。あなたはExporterのサブクラスとしてクラスを宣言している

our @ISA = qw(Exporter) 

を行い、あなたの場合は

、。 Exporterクラスはimportというメソッドを提供します。なぜそれが欲しいのですか?あなたは

use MyClass; 

を言うとき、実際に何が起こることですので:

BEGIN { 
    require 'MyClass.pm'; 
    MyClass->import; 
}; 

importメソッドが自動的たびに誰かuseがあなたのSクラスと呼ばれています。その方法はあなたが望むことを何でもすることができます。 (あなたが望むならあなた自身のimportを書くことができるかもしれませんが)通常は、呼び出し元の名前空間にシンボルをインポートするために使用されます。それはあなたのためにExporterのことです。

ただし、Exporterも独自のimportメソッドをエクスポートするので、実際にそれを継承する必要はありません。 (これはloooong時間前に修正されました。)だから今、あなただけの

use Exporter qw(import); 

を言うことができ、あなたのパッケージがまったく@ISAを台無しにせずにimportメソッドを取得します。

6

Think オブジェクト指向ここに。

Exporterは単なるモジュールではなく、クラスと考えてください。ISAの意味は「のように」「私のモジュールサブクラスのエクスポータ」です。

モジュールをExporterクラスのサブクラスとして宣言しています。つまり、便利なExporterクラスのimportメソッドを使用できます。

実際にExporterが行っていることを説明するには、Perlが名前空間を使用することを理解する必要があります。プログラムに変数があり、使用しているモジュールも$totalとなっているとします。 $total変数がモジュールの$total変数と干渉します。

これを防ぐために、Perlは名前空間を使用します。あなたのプログラムは、という名前空間mainで動作します。あなたのモジュールはpackage関数を使用して、新しい名前空間を宣言します。これで、あなたとあなたのモジュールの両方で、$totalという変数を安全に使用できます。あなたのプログラムでは、実際には$main::total、パッケージには$ Package :: Name :: total . If you want to use something from one _namespace_ in another, you can prepend the _namespace_ on it. Think of the $ File :: Find :: name and $ File :: Find :: dir variables you have when you use File :: Find`があります。

輸出者のimportメソッドが行うことは、ネームスペースから現在のネームスペースへのサブルーチン(もし望むなら、変数)をコピーすることです。 File::Copyモジュールを使用して、のメインネームスペースにをコピーする機能がないとします。あなたはまだそれを使用することができますが、あなたはそれをその上に名前空間の名前を与える必要があるだろう:

use File::Copy; 

... 

File::Copy::copy($from_file, $to_file); 

輸出業者のおかげで(とインポート方法を)、あなたはあなたのパッケージに@EXPORT配列を置く任意のサブルーチンがコピーされます現在の名前空間に上書きします。したがって、あなたはs copy`サブルーチンこのようなファイル::コピーにアクセスすることができます。

use File::Copy; 

... 

copy ($from_file, $to_file); 

これは、あなたがourなくmyとして、これらの変数のすべてを宣言しなければならない理由もあります。 my変数は語彙スコープであり、宣言されている場所の外ではアクセスできません。パッケージ変数($File::Find::nameなど)は可能です。 Exporter@EXPORT@EXPORT_OKの配列を見つけるには、パッケージの変数が必要です。

は今、エクスポート機能の望まし...私たちが知っていると行き当たりばったりの輸出サブルーチンを愛する

最も古いモジュールが付属しています。 File :: Copy、File :: Path、File :: Findを使用すると、そのサブルーチンにすぐにアクセスできます。これは、サブルーチンを配列@EXPORTに配置したためです。これは、これらの機能をすぐに利用できるようにするため、望ましいと考えられていました。私はqw(tempdir)、私はtempdir機能を使用することができなかったことを持っていなかった場合は

use File::Temp qw(tempdir); 

... 
my $temp_dir = tempdir; 

File::Tempよう

新しいモジュールをインポートするサブルーチンを宣言する必要が。

これは丁寧な考えです。モジュールは、関数をインポートする権限を要求しています。これは、サブルーチンを@EXPORT_OKに入れることによって行われます。これらは要求に応じてのみ輸出されます。

これは、必要なものだけをすべてインポートする必要がないため、優れています。そして、これらの関数が定義されている場所を文書化しています。

オブジェクト指向モジュールは何もエクスポートしないため、Exporterを使用する必要はありません。私はExporterを使用するモジュールを作成して以来、長い時間が経ちました。

- ここではおよそパッケージ変数を話しています。パッケージ変数はどこにでも表示できます。

関連する問題