Ruby中如何实现连续方法的动态调用?
解决Ruby中带点分隔的方法链动态调用问题
我太懂这种困扰了——拿到'b.this'这种字符串,直接用send肯定踩坑,因为它会傻乎乎地去找名为b.this的方法,而不是帮你拆解成b然后this的链式调用。不过别担心,我们可以写一个通用的方案,不管方法链有多长都能搞定。
问题根源
先明确为什么a.send('b.this')会报错:send方法的参数是单个方法名,它不会解析字符串里的点分隔符,所以Ruby会在A类里找b.this这个方法,自然找不到就抛NoMethodError了。而我们需要的是把字符串拆成一个个方法名,依次调用。
通用解决方案
这里有两种常用的实现方式,你可以根据场景选:
方式1:给Object扩展链式调用方法
如果你希望所有对象都能直接用这个功能,可以给Object加一个小扩展:
class Object def send_chain(method_chain) # 把方法链字符串拆成单个方法名数组 method_chain.split('.').inject(self) do |current_object, method_name| # 依次调用每个方法,把上一步的结果作为当前调用的对象 current_object.send(method_name) end end end
用你的示例测试一下:
a = A.new dynamic_string = 'b.this' a.send_chain(dynamic_string) # => 'i want this dynamically'
哪怕是更长的方法链,比如'b.some_other_method.another_one',这个方法也能完美处理。
方式2:独立工具函数(不污染全局对象)
如果不想给所有对象加方法,可以写一个独立的函数:
def call_method_chain(object, method_chain) method_chain.split('.').inject(object) { |obj, meth| obj.send(meth) } end # 调用方式 call_method_chain(a, 'b.this') # 同样返回正确结果
额外提示:处理带参数的方法链
如果你的方法链里有带参数的方法(比如'b.this(10, "hello")'),可以稍微扩展一下逻辑,解析方法名和参数部分,再把参数转换成对应类型后传递给send。不过这属于进阶需求,如果你暂时用不到,上面的基础版本完全足够。
内容的提问来源于stack exchange,提问作者Alexis Delahaye
相关产品推荐
相关产品推荐

