クラスを作成する場合:
class Foo { }
クラスはAny
、からすべてのメソッドを継承し、次にMu
。
他のクラスから継承しないクラスを作成したいと思います。そのクラスには、そのオブジェクトのインスタンスへのすべてのメソッド呼び出しをFALLBACK
キャッチする単一のメソッドが含まれている必要があります。
MetaModel
コードを調べましたが、この目標を達成する簡単な方法はないようです。すべての提案は大歓迎です!
更新:Jonathan Worthingtonが説明したように、メソッド呼び出しの方法でインターセプトを行うことにしました。これにより、CPANに2つの新しいPerl6モジュールInterceptAllMethodsとObject :: Trampolineが作成されました。
これは可能ですが、さらに努力が必要な実際的な問題に遭遇する可能性があります。構築ロジックの呼び出しは、コメントですでに指摘されている良い例です。さらに、すべてがMu
;に対して正常にタイプチェックすることが期待されます。このようなチェックは、最適化としてほとんどの場所で省略されますが、他の場所では省略されないため、さまざまなタイプのチェックの失敗が発生することが予想されます。
それはさておき、これがそれを行う方法です。まず、の新しいメタタイプをエクスポートするモジュールを作成しますclass
。
class RootHOW is Metamodel::ClassHOW {
method has_default_parent_type(|) { False }
}
package EXPORTHOW {
constant class = RootHOW;
}
Mu
そもそもメタモデルを使用して型を設定する必要があるため、ここでは(ab)通常、「いいえ、オブジェクトモデルをブートストラップしなかったため、デフォルトの親型はまだありません」というメカニズムを使用します。 "。これをモジュール(たとえば、と呼ばれるParentless
)に貼り付けると、次のように実行できます。
use Parentless;
class NotAMu {
method FALLBACK($name, |c) {
say "called $name with {c.perl}"
}
}
NotAMu.new
どの出力:
called new with \()
単にすべてのメソッドディスパッチをインターセプトすることが目標である場合、型システムを混乱させない、はるかに混乱の少ない方法があります。今のところ、メソッドキャッシュの公開を無効にするカスタムメタクラスが必要です。
class InterceptHOW is Metamodel::ClassHOW {
method publish_method_cache(|) { }
}
package EXPORTHOW {
constant class = InterceptHOW;
}
次に、次のように書くことができます。
use InterceptAllTheMethods;
class InterceptThemAll {
method ^find_method(Mu $obj, Str $name) {
return -> | { say "calling $name" }
}
}
InterceptThemAll.new
とは異なりFALLBACK
、ここでは、呼び出されるコードオブジェクトを返すことに注意してください。このfind_method
実装はメタクラスでも記述できますが、これはより適切な因数分解になる可能性があります。手元の問題を知らずに言うのは難しいです。
このアプローチでは、タイプチェックに関連する問題は発生せず、すべてのメソッドディスパッチをインターセプトできます。また、のようなものを検索しbless
て、それらをMu
実装に委任するのは簡単です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加