2

私が覚えている限り、モジュールを使用するときはいつでも use、コードの先頭に行を含めます。

最近、相互に使用する 2 つの Moose オブジェクト モジュールを作成していました。この単純すぎる例を見てください。

1 つのモジュール:

package M1 0.001;

use Moose;
use 5.010;
use namespace::autoclean;
# use M2; ### SEE QUESTION BELOW

has 'name' => (
 is       => 'ro',
 isa      => 'Str',
 required => 1,
);

has 'very_cool_name' => (
 is      => 'ro',
 lazy    => 1,
 builder => '_build_very_cool_name',
);

sub _build_very_cool_name {
 my ($self) = @_;
 my $m2 = M2->new( m1 => $self );
 return 'very ' . $m2->cool_name();
}

__PACKAGE__->meta->make_immutable;

1;

別のモジュール: パッケージ M2 0.001;

use Moose;
use 5.010;
use Data::Dumper;    # TODO DEBUG REMOVE
use namespace::autoclean;
use M1;

has 'm1' => (
 is       => 'ro',
 isa      => 'M1',
 required => 1,
);

sub cool_name {
 my ($self) = @_;
 return 'cool ' . $self->m1->name();
}

__PACKAGE__->meta->make_immutable;

1;

そして、それらを使用する短い例:

use strict;
use warnings;
use 5.010;
use M1;
use M2;

my $m1 = M1->new(name => 'dave');
say $m1->very_cool_name();

ここで、2 つのモジュールが相互に使用されていることに注意してください。M1のインスタンスを作成し、M2それを使用して を生成しますがvery_cool_nameM2は のインスタンスをM1属性として持ちます。

さて、日食でコメントを外すuse M2;M1、狂ってしまいます。それは、この「循環利用」が生み出すループだからではないでしょうか。

私はこれにコメントしuse、すべてが正常に動作しているように見えます (私は思う...) が、私は本当に不安になります (私はuseそのクラスを -ing せずにオブジェクトを使用しています!それは「合法」ですか?..)。これも私を驚かせました:

  • 本当にいつ使用する必要がありますuseか? モノを使うときは必ず使うように教わったと思います。

  • 2 つのモジュールが相互に使用する場合、何か根本的に問題がありますか (それぞれが他のモジュールのオブジェクトを使用するという意味で)。これが論理的に不可能な場合があることは知っていますが、この場合のように、理にかなっている場合もあります。 )。

4

2 に答える 2

3

Perl の観点からは問題ありません。useモジュールがすでにロードされていることを認識し、再度ロードしないほどスマートです。とはいえ、かすかなコードの匂いを嗅ぐと、相互依存が許容されるかどうか、または相互依存を排除​​するためにコードをリファクタリングする必要があるかどうかを考える必要があります。

明らかに、Eclipse はそれほど明るくありません。useエディターをなだめるためにステートメントの 1 つをコメント アウトすることはおそらく機能しますが、モジュールが (アプリケーションによって) ロードされる順序と、モジュールが相互に機能を使用するタイミングによっては、微妙なバグが発生する可能性があります。たとえば、M1 が最初に読み込まれ、読み込まれずuse M2BEGINM2 の機能を必要とするブロックがあった場合...ブーム! 実行時まで何も起こらない場合 (可能性が高い)、問題ありません。

useここでは問題ではありませんが、他のパッケージからシンボルをインポートした場合にも問題が発生します。その場合、useすべての参照を完全に修飾するためにコードを変更せずに を削除できませんでした。MyModule::function()(例:だけではなくcall function())

于 2010-10-22T14:20:43.160 に答える
2

M2 がuse M1. 実際には再帰的な依存関係はありません。

M2 が行うことは、あるオブジェクトのクラス名を検証することだけであり (M1 をロードする必要はありません)、そのオブジェクトのメソッドを呼び出します。つまり、そのオブジェクトを作成した人は誰でも M1 をロードします。

useそのクラスのオブジェクトでメソッドを呼び出すためにクラス が必要であるという規則は間違っています。useit のメソッドを直接呼び出す場合のクラス - たとえば、new. (これは純粋な OO モジュールを想定しており、明らかに、関数/シンボルをエクスポートするものではありません。)

ポリモーフィズムを考えてみましょう。これは、M1 の独自のサブクラス (M1A と呼ばれる) を作成し、M2 が M1A の存在について何も知らなくても、それを M2 に渡すことができる機能です。

于 2010-10-22T15:06:51.297 に答える