私は次のパターンを探しています。 (私はPerlで働いていますが、特に言語が重要とは思わない)。派生クラスが作成プロパティによって暗黙的に指定されているオブジェクトを作成するにはどうすればよいですか?
親クラスFooと子Bar、Baz、Bazzaを使用します。
Fooを構築する方法の1つは、文字列を解析することであり、その文字列の一部は、作成するクラスを暗黙指定します。たとえば、 'http:'を起動するとBarですが、それには '[Date]'が含まれていればBazはそれを好きです。
Fooがすべての子を知っていて、どの文字列がBarであるか、Bazなどは、適切なコンストラクタを呼び出すことができます。しかし、基本クラスはその子どもについての知識を持っていてはなりません。
私が望むのは、Fooのコンストラクタが子供たちを順番に試すことができることです。そのうちの1人が「はい、これは私です。私はその物を作成します」と言うまでです。
一般的なケースでは、この問題は明確に定義されていません。文字列を受け入れる複数の子が存在する可能性があります。したがって、それらは問題と呼ばれる順序です。これを無視して、文字列の特性は、文字列が好きな子クラスが1つだけであるようなものです。
ベストは、子クラスが初期化時に基本クラスに「登録」して、コンストラクタのリストを取得し、それらをループすることです。しかし、私が欠けているより良い方法がありますか?
サンプルコード:
package Foo;
my @children;
sub _registerChild
{
push @children, shift();
}
sub newFromString
{
my $string = shift;
foreach (@children) {
my $object = $_->newFromString(@_) and return $object;
}
return undef;
}
package Bar;
our @ISA = ('Foo');
Foo::_registerChild(__PACKAGE__);
sub newFromString
{
my $string = shift;
if ($string =~ /^http:/i) {
return bless(...);
}
return undef;
}
ありがとうございます。 Logical Module :: Pluggableは、まさに私が探していたものです。ユーザーのマシンには存在しない可能性があるため、私たちの状況には理想的ではないかもしれないので、独自のモジュールで配布する必要があります。 登録ソリューションに比べて「魔法」なので、あまり明確ではないでしょう。 しかし、それを私の注意を引くことに感謝します。 –
これは魔法のようなものですが、デフォルトの動作ではMyClass :: Pluginネームスペースでのみクラスがロードされます(ネームスペースは簡単にオーバーライドできます)。したがって、登録はその名前空間にモジュールを作成することと事実上同じです。 明らかに、CPANモジュールですが、最近CPANを使わずにPerlで重大なアプリケーションを管理できれば驚くでしょう。 –