[已重写]ruby重命名特殊方法(或类方法)
ruby吧
全部回复
仅看楼主
level 1
876加几 楼主
在没有任何先例的情况下,我经过攻坚,成功研发出ruby重命名特殊方法的代码。
众所周知,ruby原装的alias和alias_method均只能重命名实例方法和全局变量,而不能重命名特殊方法。然而,在某些极端特殊情况下(如使用ruby语言的RM系列游戏制作软件重定义类方法,以达到游戏内部控制音量大小)必须要重定义类方法,因此,进过攻坚,研发出了ruby重命名特殊方法的代码。代码如下:
=======================================================================
$_aliased_singleton_methods = []
def alias_singleton_method(new_method, old_method)
str = old_method.to_s.split(".")
str.pop
$_aliased_singleton_methods.push(eval((str + ["method(old_method.split('.')[-1]).clone"]).join(".")))
size = $_aliased_singleton_methods.size
arity = eval((str + ["method(old_method.split('.')[-1]).arity"]).join("."))
num = arity
if num < 0
num = -1 - num
end
ary = []
for i in 0...num
ary.push("arg#{i}")
end
arg_string = arity < 0 ? (ary + ["*arg"]).join(",") : ary.join(",")
eval("def " + new_method.to_s + "(" + arg_string + ");args = [];if defined? arg;for i in 0...arg.size;args.push('arg[' + i.to_s + ']');end;end;eval('$_aliased_singleton_methods[" + (size - 1).to_s + "].call(' + (" + ary.inspect + " + args).join(',') + ')');end")
end
=======================================================================
注解:
=======================================================================
使用方法:alias_singleton_method 新方法, 原方法
例:
=======================================================================
module A
def self.a(x, y)
puts [x, y]
end
end
alias_singleton_method "A.b", "A.a" # 重命名特殊方法A.a
A.a(1, 2) # => [1, 2]
A.b(1, 2) # => [1, 2]
module A
def self.a(x, y) # 重定义A.a
puts [y, x]
end
end
A.a(1, 2)
# => [2, 1] #
已重定义
A.b(1, 2)
# => [1, 2] #
无影响
=======================================================================
注:
1.灵感来自我以前追加定义js内部函数的方法;
2.alias_singleton_method亦可以重命名实例方法,但是这样做一是高射炮打蚊子,二是可能会造成对象无法被Marshal写入文件。
3.生成的新方法完全等价于(但并不是)原方法(包括参数数量),可以用于追加定义。
=======================================================================
总结:这个代码使重定义特殊方法变得可操作,追加特殊方法不再是难事。
2018年01月31日 06点01分 1
level 8
其实Ruby中并没有什么特殊方法,所谓类方法其实只是这个类的singleton class(也有人译做单例类)的实例方法,而方法本身无非只是UnboundMethod或Method。
下面的代码可以解释这一点:
其中第7/8行代码是同样效果,第7行也适用于早期版本Ruby。
如果想把第7行包装起来,又可以写成下面这个样子:
这里的strong_alias可以为所有的Module/Class设置类方法别名。其实还可以把第一行中的Module改成Object,这样可以给任意对象(除BasicObject类型)设置方法别名,因为类本身从另个角度看也只是一个Class类型的对象罢了。
至于追加定义方法,可以用同样的思路进行,不用这么麻烦的。
2018年04月05日 08点04分 2
挺简单聪明的一个办法[真棒]
2018年05月05日 13点05分
1