Perlでポリモーフィズムがどのように機能するかについての説明がわかりません。私はポリモーフィズムが何を意味するのか理解していますが、それがperl内でどのように内部的に機能するかを理解しようとしています。誰かがそれを説明するいくつかのドキュメントを私に指摘できますか?私が行ったすべてのグーグル検索は、perlのポリモーフィズムの例を示していますが、perlがそれをどのように機能させるかについては示していません。
5 に答える
メソッドがオブジェクトまたはクラスで呼び出されると、 Perlはそのメソッドがクラス自体によって直接提供されているかどうかを確認します。
クラスは単にPerlパッケージであるため、サブルーチンの存在を探すだけです&Class::method
。
そのようなサブルーチンが見つからない場合、Perlはクラスの基本クラスのリストを含む@ISA
同じパッケージ(つまり)内の配列を調べ、そこにあるすべてのパッケージ/クラスに対して同じチェックを行います。@Class::ISA
これらの各クラスにも@ISA
配列が含まれている可能性があるため、検索は再帰的に行われます。
最後に、メソッドがこのメソッドのどこにも見つからない場合、PerlはUNIVERSAL
サブルーチンの特別なパッケージを探します&UNIVERSAL::method
。
この時点で失敗するとAUTOLOAD
システムが呼び出されますが、それは実際には多型の原則を超えています。
どこかで適切なマッチング方法が見つからないと、例外が発生します。
Object Oriented Perl、Damian Conway、Manning(2000)の第7章は、ポリモーフィズムと呼ばれています。10ページ。
ただし、C ++、Java、C#などを使用している場合は、Perlの「ポリモーフィズム」について知ることはあまりありません。ポリモーフィズムの概念は、Perlよりも物事を複雑にしているとさえ言えます。
Perlプログラマーが理解しようと努力すべきメカニズムは、メソッドルックアップがどのように機能するかだと思います。答えは次のとおりです@ISA
。パッケージの配列を介した深さ優先の再帰スキャン。
例として、やってみましょう$o->bla
。の実装がないパッケージに$o
恵まれています。ただし、最初から継承し、次に()を継承します。それでは、最初にルックアップを実行しましょう。メソッドも定義していません。親クラスがある場合は、そこで検索を続行します。しかし、そうではありません。そこで、ここで調べます。幸い、メソッドがあります。そうしないと、最後の手段のパッケージである、も定義されていないため、実行時エラーになります。A
bla
B
C
@ISA = ('B', 'C')
B
C
UNIVERSAL
bla
オブジェクトメソッド呼び出しは、基本的に次の最適化された*バージョンです。
my $class = ref($_[0]);
my @isa = mro::get_linear_isa($class);
for my $pkg (@isa) {
if (exists(&{$pkg.'::'.$method_name})) {
return &{$pkg.'::'.$method_name};
}
}
ref
オブジェクトに関連付けられているクラスの名前を取得します。クラスはオブジェクトの変数に格納されます。
$ perl -MDevel::Peek -e'my $o = {}; Dump($o); bless($o, "SomeClass"); Dump($o);'
SV = IV(0x9e4ae0c) at 0x9e4ae10
REFCNT = 1
FLAGS = (PADMY,ROK)
RV = 0x9e317d0
SV = PVHV(0x9e36808) at 0x9e317d0
REFCNT = 1
FLAGS = (SHAREKEYS)
ARRAY = 0x0
KEYS = 0
FILL = 0
MAX = 7
RITER = -1
EITER = 0x0
SV = IV(0x9e4ae0c) at 0x9e4ae10
REFCNT = 1
FLAGS = (PADMY,ROK)
RV = 0x9e317d0
SV = PVHV(0x9e36808) at 0x9e317d0
REFCNT = 1
FLAGS = (OBJECT,SHAREKEYS) <----
STASH = 0x9e323d0 "SomeClass" <----
ARRAY = 0x0
KEYS = 0
FILL = 0
MAX = 7
RITER = -1
EITER = 0x0
get_linear_isa
@ISA
はパッケージ内に基づいており$class
、パッケージ内で@ISA
名前が付けられています。
クラス名はオブジェクト内にあり、Perlは実行時にそのシンボルテーブルをチェックできるため、ポリモーフィズムを提供するために仮想メソッドテーブルは必要ありません。
* —クラス$classのメソッド$method_nameを提供するパッケージをキャッシュします。また、線形ISA全体を事前に計算するのではなく、必要に応じて計算します。
これは、継承ベースのポリモーフィズムによく適合し、Perlが具体的に何をするかについてのアイデアを提供します。私はいつも12.5章を使いました。これらのもののリファレンスとしてのプログラミングPerlのクラス継承。
ポリモーフィズムとは、異なるタイプのオブジェクトが同じ名前のメソッド呼び出しに応答するという単純な考え方です。Perlのように弱く型付けされた言語は、「暗黙的に多形性」です。
たとえば、CGI
オブジェクト、Apache2::Request
オブジェクト、およびPlack::Request
オブジェクトにはすべてparam
、HTTPリクエストのパラメータを返すメソッドがあります。オブジェクトをパラメーターとして受け入れる関数を記述し、param
そのオブジェクトのメソッドを呼び出して、オブジェクトのタイプを知らなくてもHTTP要求パラメーターを取得することができます。
強く型付けされた言語は、関数がパラメーターのデータ型を指定するため、このようには機能しません。Dog
のいずれかを予期している場合、タイプのオブジェクトを使用してJavaで関数を呼び出すことはできませんCat
。したがって、強く型付けされた言語は、ポリモーフィズムを可能にする特別なメカニズムを作成する必要があります。