7

Perlでポリモーフィズムがどのように機能するかについての説明がわかりません。私はポリモーフィズムが何を意味するのか理解していますが、それがperl内でどのように内部的に機能するかを理解しようとしています。誰かがそれを説明するいくつかのドキュメントを私に指摘できますか?私が行ったすべてのグーグル検索は、perlのポリモーフィズムの例を示していますが、perlがそれをどのように機能させるかについては示していません。

4

5 に答える 5

15

メソッドがオブジェクトまたはクラスで呼び出されると、 Perlはそのメソッドがクラス自体によって直接提供されているかどうかを確認します。

クラスは単にPerlパッケージであるため、サブルーチンの存在を探すだけです&Class::method

そのようなサブルーチンが見つからない場合、Perlはクラスの基本クラスのリストを含む@ISA同じパッケージ(つまり)内の配列を調べ、そこにあるすべてのパッケージ/クラスに対して同じチェックを行います。@Class::ISA

これらの各クラスにも@ISA配列が含まれている可能性があるため、検索は再帰的に行われます。

最後に、メソッドがこのメソッドのどこにも見つからない場合、PerlはUNIVERSALサブルーチンの特別なパッケージを探します&UNIVERSAL::method

この時点で失敗するとAUTOLOADシステムが呼び出されますが、それは実際には多型の原則を超えています。

どこかで適切なマッチング方法が見つからないと、例外が発生します。

于 2012-06-13T17:47:57.517 に答える
9

Object Oriented Perl、Damian Conway、Manning(2000)の第7章は、ポリモーフィズムと呼ばれています。10ページ。

ただし、C ++、Java、C#などを使用している場合は、Perlの「ポリモーフィズム」について知ることはあまりありません。ポリモーフィズムの概念は、Perlよりも物事を複雑にしているとさえ言えます。

Perlプログラマーが理解しようと努力すべきメカニズムは、メソッドルックアップがどのように機能するかだと思います。答えは次のとおりです@ISA。パッケージの配列を介した深さ優先の再帰スキャン。

例として、やってみましょう$o->bla。の実装がないパッケージに$o恵まれています。ただし、最初から継承し、次に()を継承します。それでは、最初にルックアップを実行しましょう。メソッドも定義していません。親クラスがある場合は、そこで検索を続行します。しかし、そうではありません。そこで、ここで調べます。幸い、メソッドがあります。そうしないと、最後の手段のパッケージである、も定義されていないため、実行時エラーになります。AblaBC@ISA = ('B', 'C')BCUNIVERSALbla

于 2012-06-13T17:57:20.380 に答える
5

オブジェクトメソッド呼び出しは、基本的に次の最適化された*バージョンです。

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全体を事前に計算するのではなく、必要に応じて計算します。

于 2012-06-13T18:22:22.530 に答える
1

これは、継承ベースのポリモーフィズムによく適合し、Perlが具体的に何をするかについてのアイデアを提供します。私はいつも12.5章を使いました。これらのもののリファレンスとしてのプログラミングPerlのクラス継承。

于 2012-06-13T17:20:21.577 に答える
1

ポリモーフィズムとは、異なるタイプのオブジェクトが同じ名前のメソッド呼び出しに応答するという単純な考え方です。Perlのように弱く型付けされた言語は、「暗黙的に多形性」です。

たとえば、CGIオブジェクト、Apache2::Requestオブジェクト、およびPlack::Requestオブジェクトにはすべてparam、HTTPリクエストのパラメータを返すメソッドがあります。オブジェクトをパラメーターとして受け入れる関数を記述し、paramそのオブジェクトのメソッドを呼び出して、オブジェクトのタイプを知らなくてもHTTP要求パラメーターを取得することができます。

強く型付けされた言語は、関数がパラメーターのデータ型を指定するため、このようには機能しません。Dogのいずれかを予期している場合、タイプのオブジェクトを使用してJavaで関数を呼び出すことはできませんCat。したがって、強く型付けされた言語は、ポリモーフィズムを可能にする特別なメカニズムを作成する必要があります。

于 2012-06-13T20:46:07.040 に答える