假设我们有一个方法
MyClass>>#method: arg
Transcript crShow: 'executed'
所以当你做MyClass new method: 1
时,转录本被"执行"行填充。
现在我想跳过这个方法,如果arg
是0。我试图安装一个而不是 metalink,条件是:
link := MetaLink new
condition: [ :arguments |
arguments first = 0 ]
arguments: #(arguments);
control: #instead.
(MyClass >> #method:) ast link: link
但是这个方法不会再运行了我想在参数不为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
应该返回一个编译的方法,而不是反射的对应
是的,看起来"代替钩子"总是执行"代替"原始方法,即使链接条件不成立,区别只是我们是否返回代替链接评估的值或只是nil。
也许这应该改为链接。
作为您的用例的解决方案,您可以使用before链接,如果条件成立,它只返回接收者:
| 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)的关键