例
out.pl:
(my|our|local|global|whatever???) var = "test";
require("inside.pm");
内部.pm:
print $var;
私はパッケージを使いたくありません - それは私のニーズを圧倒しています :) ありがとう!
宣言を使用しない場合でも、常にパッケージを使用しています。package
デフォルトでは、パッケージで作業していますmain
。
宣言するすべての変数our
はパッケージ変数であり、パッケージ全体で使用できる必要があります。次に例を示します。
#! /usr/bin/env perl
# test2.pl
use strict;
use warnings;
our $foo = "bar";
1;
はパッケージ変数として宣言されているため$foo
、他のプログラムで使用できます。
#! /usr/bin/env perl
use strict;
use warnings;
require "test2.pl";
our $foo;
print "The value of \$foo is $foo\n";
今、私はあなたに十分なロープを与えました、私はあなたにそれでぶら下がらないように言うつもりです。
これは本当に、本当に悪いアイデアです。$foo
理解するのがほとんど不可能なある種の不思議なメカニズムから価値を得ることに注意してください。
パッケージが複雑すぎますか?本当に?それほど難しいことではありません!この例を見てください:
#! /usr/bin/env perl
# test2.pm
package test2;
use strict;
use warnings;
our $foo = "bar";
1;
package
宣言を追加し、のtest2.pm
代わりにプログラムを呼び出すことを除いて、以前と大差ありませんtest2.pl
。
アクセス方法は次のとおりです。
#! /usr/bin/env perl
use strict;
use warnings;
use test2;
print "The value of \$foo from package test2 is $test2::foo\n";
私がしなければならなかったのは、変数でパッケージ名を使用することだけでした。これは悪いアイデアですが、上に示した本当に悪いアイデアよりもはるかに優れています。
少なくとも、あなたはその価値がどこから来たのかを知っています。それはから来ましたtest2.pm
。また、サブルーチンで設定すれば、変数にアクセスできます。
#! /usr/bin/env perl
# test2.pm
package test2;
use strict;
use warnings;
sub fooloader {
our $foo = "bar";
}
1;
$foo
がサブルーチンに設定されていることに注意してくださいfooloader
。そして、これがそれにアクセスするための私の他のプログラムです:
#! /usr/bin/env perl
use strict;
use warnings;
use test2;
&test2::fooloader();
print "The value of \$foo from package test2 is $test2::foo\n";
これで、エクスポーターを使用してサブルーチン(さらには変数)をエクスポートできますが、それはもうあまり目にすることではありません。主にそれが本当に悪いアイデアだからです。元のREALLYREALLYBAD IDEAほど悪くはありませんが、上記のBADIDEAよりも悪いです。
#! /usr/bin/env perl
# test2.pm
package test2;
use base qw(Exporter);
our @EXPORT = qw(fooloader);
use strict;
use warnings;
sub fooloader {
our $foo = "bar";
}
1;
fooloader
これで、パッケージ名なしでサブルーチンを使用できます。
#! /usr/bin/env perl
use strict;
use warnings;
use test2;
fooloader();
print "The value of \$foo from package test2 is $test2::foo\n";
fooloader
もちろん、問題は、サブルーチンがどこから来ているのか実際にはわからないということです。@EXPORT_OK
の代わりにを使用した場合は、関数がどこから来たのか@EXPORT
を使用use test2 qw(fooloader);
して文書化することができます。また、独自のプログラムで独自の関数を作成せず、インポートした関数をオーバーライドしfooloader
ないようにすることも役立ちます。fooloader
次に、なぜプログラムが機能しなくなったのか疑問に思います。
ちなみに、関数だけでなく変数もエクスポートできます。しかし、それは本当に、本当に、本当に悪いものになります-そもそもパッケージを使用するすべての理由に違反するため、ひどいアイデアはありません。あなたがそれをするつもりなら、なぜパッケージを気にするのですか?簡単に銃を持って足を撃ってみませんか?
最良かつ好ましい方法は、オブジェクト指向のPerlを使用し、それを完全に正しい方法で行うことです。何が起こっているのか、そしてその理由を正確に知る方法。また、コードが何をしているのかを簡単に把握できます。エラーを最小限に抑える方法。
完全にオブジェクト指向のTest2クラスに注目してください。
#! /usr/bin/env perl
# Test2.pm
package Test2;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub FooValue {
return "bar";
}
1;
そして、そのTest2
クラスを使用します。
#! /usr/bin/env perl
use strict;
use warnings;
use Test2;
my $tester = Test2->new;
print "The value of foo from package test2 is " . $tester->FooValue . "\n";
これが最善の方法である理由は、パッケージを使用している場合でも、の値を操作でき、$test2::foo
プログラム全体で変更されるためです。$constants::pi
これが言われ、どこかで3.14159から3に変更したと想像してみてください。それ以降、を使用$constants::pi
すると間違った値になります。オブジェクト指向メソッドを使用する場合、Constant->Piメソッドの値を変更することはできません。常に3.14159になります。
それで、私たちは今日何を学びましたか?
Perlでは、本当に、本当に悪いアイデアを実行するのは非常に簡単であることがわかりましたが、パッケージを使用するのにそれほど多くの作業は必要ないため、単に悪いアイデアになります。そして、オブジェクト指向のPerlを少し学び始めた場合、実際には、あまり労力をかけずに、すべてを完全に正しい方法で行うことができます。
選択はあなた次第です。あなたが撃っている足はおそらくあなた自身のものであることを覚えておいてください。
で動作しour
ます。
$ cat out.pl
our $var = "test";
require("inside.pm");
$ cat inside.pm
print "Testing...\n";
print "$var\n";
$ perl out.pl
Testing...
test
これour
は$var
グローバルになるため機能し、定義inside.pm
されたスコープで実行されます。$var
推奨されるテクニックかどうかはわかりませんが、興味深い質問です。
編集:コメントに基づいて回答を明確にする必要があります(パッチは大丈夫です):
our
現在のレキシカル スコープ内で使用するために、単純な名前を現在のパッケージのパッケージ (グローバル) 変数に関連付けます。つまり、はまたはour
と同じスコープ規則を持ちますが、必ずしも変数を作成するとは限りません。my
state
したがって、 を使用すると、現在のパッケージ (ここではおそらく)our
を取得し、そのスコープで使用できます。実際には、必要なファイル内のコードに対して「グローバル」になります。$var
main
変数はデフォルトでグローバルになるため、真のグローバルはなしで導入されます。our
しかし、私はそれらを推奨する人を知りません。