Perlでメソッド呼び出しを傍受し、引数で何かを実行してから実行できますか?Perlのメソッド呼び出しをインターセプトできますか?
答えて
はい、Perlサブルーチンコールを代行受信できます。私はMastering Perlにそのようなことに関する章全体を持っています。 Hook::LexWrapモジュールをチェックしてください。このモジュールを使用すると、すべての詳細を調べなくても実行できます。 Perlのメソッドは単なるサブルーチンです。
サブクラスを作成し、キャッチするメソッドをオーバーライドすることもできます。これは、オブジェクト指向プログラミングがあなたが望んでいる方法であるため、これを行うためのやや良い方法です。しかし、時々人々はこれを適切に行うことを許さないコードを書くことがあります。 Mastering Perlにそれに関する詳細があります。
これはMooseの仕事のようです。 MooseはPerlのためのオブジェクトシステムであり、これを行うことができます。 docsは私ができるよりはるかに良い説明をしますが、おそらくMethod Modifier、具体的にはbefore
です。
ムースは、アプリケーション全体で使用するものであり、対象となる問題ではありません。 –
しかし、それは問題が何であるかによって異なり、質問の質問者は詳細を述べていません。新しいアプリケーションを作成するときに取るアプローチを評価している人がいるかもしれません。その場合、Mooseを有効にすることは適切で有益な応答になります。 – jsoverson
同じことを言っただけです。私はムーゼを使わないと言っていませんでしたが、私はそれを使用すると言っていませんでした。 –
簡単に説明すると、Perlはシンボルテーブルを変更する適性があります。メソッドの属するパッケージのシンボルテーブルを介してサブルーチン(メソッド)を呼び出します。シンボルテーブルを変更した場合(これは非常に汚いとはみなされません)、ほとんどのメソッド呼び出しを、指定した他のメソッドを呼び出すことで置き換えることができます。
# The subroutine we'll interrupt calls to
sub call_me
{
print shift,"\n";
}
# Intercepting factory
sub aspectate
{
my $callee = shift;
my $value = shift;
return sub { $callee->($value + shift); };
}
my $aspectated_call_me = aspectate \&call_me, 100;
# Rewrite symbol table of main package (lasts to the end of the block).
# Replace "main" with the name of the package (class) you're intercepting
local *main::call_me = $aspectated_call_me;
# Voila! Prints 105!
call_me(5);
また、これは、誰かがサブルーチンのリファレンスを取り、参照を経由して、それを呼び出した後、あなたは、もはやこのような呼び出しに影響を与えることはできない、ということを示しています。これは、アプローチを示しています。
私は確かに、perlでアスペクトを行うためのフレームワークがあると確信していますが、これはアプローチを示しています。
はい。ちょうど別の動的スコープの変数である@_
にあるコールに
引数:
は、次の3つのものを必要としています。
次に、goto
は、現在の@_
を保持するが、別の(テール)関数呼び出しを行うreference-sub引数をサポートしています。
最後に、local
を使用して、レキシカルスコープのグローバル変数を作成し、シンボルテーブルを%::
に埋め込みます。
だからあなたが持っている:
sub foo {
my($x,$y)=(@_);
print "$x/$y = " . ((0.0+$x)/$y)."\n";
}
sub doit {
foo(3,4);
}
doit();
もちろん出力した:
3/4 = 0.75
我々はlocal
を使用してFOOを交換して行くことができます:
my $oldfoo = \&foo;
local *foo = sub { (@_)=($_[1], $_[0]); goto $oldfoo; };
doit();
そして今、我々が得ます:
4/3 = 1.33333333333333
あなたは、その名前を使用せずに*foo
を変更したい、とあなたは、あなたが例えば、%::
を操作して、それを修正することができ、eval
を使いたくなかった場合:
$::{"foo"} = sub { (@_)=($_[0], 1); goto $oldfoo; };
doit();
そして今、我々が得る:
3/1 = 3
パベルはそれを行う良い方法を説明していますが、なぜこれを最初にやりたいのかについて詳しく説明する必要があります。
任意のサブルーチンへの呼び出しをインターセプトする高度な方法を探している場合は、シンボルテーブルを使った操作がうまくいくはずですが、現在作業している名前空間にエクスポートされた関数に機能を追加するには、他の名前空間に存在する関数を呼び出す方法を知る必要があります。
Data :: Dumperは、通常、関数 'Dumper'を呼び出し元の名前空間にエクスポートしますが、その関数をオーバーライドまたは無効にして独自のDumper関数を提供し、完全修飾名で元の関数を呼び出します。
use Data::Dumper;
sub Dumper {
warn 'Dumping variables';
print Data::Dumper::Dumper(@_);
}
my $foo = {
bar => 'barval',
};
Dumper($foo);
また、これは元の問題によっては、より適切な代替ソリューションです。シンボルテーブルを使って遊ぶときには楽しいことがたくさんありますが、余計なことがあり、必要がない場合はコードを維持するのが難しくなります。
この場合、何もインポートしないようにダンプに空のインポートリストを与えるべきです。また、この場合シーケンスが重要です。最初にインポートしてからオーバーライドする必要があります。最後のサブルーチン定義が勝つ。最後に、警告の下で、これを行う '再定義'エラーが発生します。 –
間違いなく、単に例のために単純にしておきます。直接的であれば、すべての接線の詳細を説明するよりも、より価値があります(レスポンダにとってはより早い)。インポートと警告の概念は、とにかく他の質問として最もよく説明されます。 – jsoverson
- 1. メソッド呼び出しのトラッキング/インターセプト
- 2. JUnit:メソッド呼び出しをインターセプトし、別のパラメータで呼び出す
- 3. すべての客観的なcメソッド呼び出しをインターセプト
- 4. 参照モニタへのメソッド呼び出しをインターセプトしていますか?
- 5. 他のオブジェクトからメソッドを呼び出すメソッド呼び出し
- 6. インターセプト動的関数呼び出し
- 7. C#でメソッド/呼び出しを別のメソッドから呼び出す方法は?
- 8. CGLibメソッドのインターセプトまたはJDKメソッド呼び出しのreturnオブジェクトの意味は何ですか? CGLIBプロキシの方法インターセプトで
- 9. Perl関数呼び出し
- 10. C#で別のメソッド呼び出しイベントでメソッドをトリガできますか?
- 11. コンパイラはメソッド呼び出しを最適化できますか?
- 12. 1回の呼び出しでメソッドを呼び出す
- 13. Python:関数のパラメータを変更するメソッド呼び出しをインターセプトする方法はありますか?
- 14. requestFinishedメソッドでメソッドを呼び出す際にクラッシュしますか?
- 15. Spring AOP @AfterThrowing - メソッドの詳細を呼び出すメソッドの呼び出し(メソッドを呼び出さない)
- 16. Perl CGI onclickはperlサブルーチンを呼び出します
- 17. ヘルパーメソッドを呼び出すページのヘルパークラスからメソッドを呼び出します。
- 18. 一致するメソッドへの呼び出しをインターセプトする方法はありますか?
- 19. メソッドを呼び出すか?
- 20. javaからperlを呼び出す
- 21. Makeからperlスクリプトを呼び出す
- 22. JavaScriptからPerlスクリプトを呼び出す
- 23. perlからストアドプロシージャを呼び出す
- 24. rootViewControllerでメソッドを呼び出すことはできますか?
- 25. Windowsサービスでのメソッド呼び出しの呼び出し
- 26. 各メソッド呼び出しでjQueryがコンストラクタを呼び出す
- 27. テストのメソッド呼び出しを「インターセプト」するにはどうすればよいですか?
- 28. メソッド呼び出し
- 29. シェルスクリプトでperlサブルーチンを呼び出す
- 30. メソッドを呼び出すときのValueError
「aop」というタグを使用しています。あなたが使用したい特定のAOPテクニックについて質問してみませんか? (あなたの質問に対する答えは、AOPシステムを実装するのに役立つかもしれませんが、他の誰かがすでにそれをしているときにどうしますか?) – jrockway
これはメソッド属性で行うことができると思っていましたが、今は適切なperldocページ私が考えていたページではありません)。私はロギングを追加するためのさまざまなメソッドをラップすることを含む素晴らしい例を思い出してください... – Ether
追加情報については、この関連する質問を参照してください:http://stackoverflow.com/questions/635212/how-i-default-perl-class-methods – draegtun