使用 MetaLinks 有条件地跳过方法

Conditionally skip a method with MetaLinks

假设我们有一些方法

MyClass>>#method: arg

    Transcript crShow: 'executed'

因此,当您执行 MyClass new method: 1 时,成绩单将充满 "executed" 行。

现在,如果 arg 为 0,我想跳过此方法。我尝试安装一个 而不是 元链接,条件是:

link := MetaLink new
   condition: [ :arguments |
      arguments first = 0 ]
   arguments: #(arguments);
   control: #instead.

(MyClass >> #method:) ast link: link

但是该方法不再 运行,如果 arg 不为 0,我想 运行 它。

我也试过用这种方式在元对象中做条件:

link := MetaLink new
   metaObject: [ :ast :arguments :receiver | 
      arguments first = 0
      ifFalse: [
         ast compiledMethod
            valueWithReceiver: receiver
            arguments: arguments ] ];
   selector: #value:value:value:;
   arguments: #(node arguments receiver);
   control: #instead.

(MyClass >> #method:) ast link: link

但在这种情况下,你最终会陷入无限递归,因为元链接被一遍又一遍地调用,尽管我认为 ast compiledMethod 应该 return 一个编译方法而不是反射对应物

是的,看起来"instead hooks"总是执行原方法的"instead",即使link条件不成立,区别只是我们是否[=26] =] 取而代之 link 评估的价值或只是 nil.

也许应该改为 links。

作为您的用例的解决方案,您可以使用 link 之前的 return 如果条件成立,则接收者只是 return:

| ml |
ml := MetaLink new.
ml control: #before.
ml condition:[:args | args first = 0] arguments:#(arguments).
ml selector:#value:.
ml metaObject:[:context | context return].
ml arguments:{#context}.

(MyObject>>#method:) ast link:ml.

#context 是 thisContext 细化 (RFThisContextReification) 的关键