7

引き継いだコードを調べていると、次の行に出くわしました。

 my @files = My::Module::DB::raw_info->search_like(customer_handle => $config->{client}, feed => $config->{site}, arrival =>"$date")

これが というパッケージから配列を返すことはわかっていますMy::Module::DB::raw_info

私が確信していないのは(そして私はOOPを学んでいるだけです)、何->search_likeを指すかです。

私はそれを変数またはサブルーチンとして見ませんでしたMy::Module::DB::raw_info

ヒントをいただければ幸いです。私はこのことを学び始めたばかりです。火を浴びているようなものです。(後でもっと幸せになることはわかっていますが) うん!

4

6 に答える 6

8

これはおそらく、メソッドが基本クラスから継承されているためです。ただし、非常に奇妙な状況では、モジュールの名前空間に動的に注入することもできますが、これを理解するのははるかに困難です。

力ずくで検索するか、モジュールの基本クラス (およびおそらく継承チェーンの上位) を見つけ出し、基本クラスのコードだけを検索することによって、サブルーチンを見つけることができます。両方を行う方法を示します。


ブルート フォース検索: これはおそらく、複雑なケースでは最も簡単な解決策です。サブルーチンが非祖先モジュールによってモジュールの名前空間に動的に注入された可能性があり、祖先モジュールを見つけることは、継承を定義する複数の方法が原因で 100% 簡単ではないためです。使用 (ベースを使用、親を使用、Moose のもの、AUTOLOADED のもの)

まず、My::Module でロードされている他のモジュールを見つけます。

perl -e 'use My::Module::DB::raw_info; print "$INC{$_}\n" foreach keys %INC'

これにより、これらすべてのモジュールの場所が出力されます

次に、そのすべてのコードでサブ定義を検索します (以下はすべて 1 行である必要があります。読みやすくするために 2 行に分割しています)。

grep search_like 
   `perl -e 'use My::Module::DB::raw_info; print "$INC{$_}\n" foreach keys %INC'`

返される結果が多すぎる場合は、grep を次のように変更します。

grep "sub search_like"
   `perl -e 'use My::Module::DB::raw_info; print "$INC{$_}\n" foreach keys %INC'`

これにより、モジュールコードの継承を実際に分析することなく、My::Module::DB::raw_info が継承するモジュールの定義を見つけることができます。


継承:

ISA次のように使用して、モジュールの親を見つけます。

perl -e 'use My::Module::DB::raw_info; print "@My::Module::DB::raw_info::ISA\n";'

@ISA明確にするために、これはMooseのものではなく、を使用する「古典的に継承された」モジュールに対してのみ機能します。また、ルーチンが AutoLoader を使用して呼び出された場合、またはシンボル テーブルに動的に挿入された場合にも機能しません。これは、必ずしも親コードではなく、任意のコードで発生する可能性があります。

于 2010-10-27T15:00:34.853 に答える
5

難問の原因として考えられるのは、 My::Module::DB が他のクラスを拡張していることです。の行に沿ってブロックを探します

use parent Some::Module;

また

BEGIN { extends Some::Module }

My/Module/DB.pm の上部付近

編集:一部のコメンターが以下で有益に指摘しているように、Perl クラスをサブクラス化する方法はいくつかありますが、これらはおそらく最も一般的なものです。(多分。)

于 2010-10-27T14:53:42.797 に答える
2

コアDevel::Peekモジュールを使用して、サブルーチン参照に保持されている内部データを調べることができます。

OO メソッドからサブルーチン参照を取得するには->can(...)、すべてのオブジェクトのメソッドを使用します。

my $code_ref = My::Module::DB::raw_info->can('search_like');

次に、情報を印刷できます。

use Devel::Peek 'Dump';

Dump($code_ref);

のドキュメントによるとDevel::Peek、次のようなものを取得する必要があります。

サブルーチンへの参照は次のようになります。

    SV = RV(0x798ec)
      REFCNT = 1
      FLAGS = (TEMP,ROK)
      RV = 0x1d453c
    SV = PVCV(0x1c768c)
      REFCNT = 2
      FLAGS = ()
      IV = 0
      NV = 0
      COMP_STASH = 0x31068  "main"
      START = 0xb20e0
      ROOT = 0xbece0
      XSUB = 0x0
      XSUBANY = 0
      GVGV::GV = 0x1d44e8   "MY" :: "top_targets"
      FILE = "(eval 5)"
      DEPTH = 0
      PADLIST = 0x1c9338

これは、

  • サブルーチンは XSUB ではありません (START と ROOT がゼロではなく、XSUB がゼロであるため)。
  • パッケージ main でコンパイルされたこと。
  • MY::top_targets という名前で;
  • プログラムの 5 番目の eval 内。
  • 現在実行されていません (DEPTH を参照)。
  • プロトタイプはありません (PROTOTYPE フィールドがありません)。

したがって、COMP_STASH はコードがコンパイルされた場所を示し、GVGV::GV はサブの完全な名前を示します。

于 2010-10-27T19:31:01.920 に答える
1

おそらくそれはいくつかの継承されたメソッドです。Perl の継承について少し読ん@ISAで、モジュール定義で割り当てを検索してください。

于 2010-10-27T15:03:54.570 に答える
1

メソッドは、 のスーパークラスで定義できますMy::Module::DB::raw_info。への呼び出しの前に次の行を挿入しますsearch_like

print @My::Module::DB::raw_info::ISA;

これらのクラスを見てみましょう。

これが機能しない場合は、Devel::PeekDump()を使用して、サブルーチンがどこから来たのかを確認できます。

use Devel::Peek;
Dump(\&search_like);

出力で を探しGVGV::GV partます。

于 2010-10-27T15:01:25.063 に答える
1

「よくわからないのですが、OOP を学んでいるところです (開発者がクビになったおかげで)、これが "->search_like" の参照です。」名前と値のペアを入力パラメーターとして使用します ( Perl クックブック セクション 10.7 )。

参考までに、私が非常に役立つと思うもう 1 つの本はProgramming Perlです。

于 2010-10-27T16:23:42.407 に答える