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
众所周知,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.生成的新方法完全等价于(但并不是)原方法(包括参数数量),可以用于追加定义。
=======================================================================
总结:这个代码使重定义特殊方法变得可操作,追加特殊方法不再是难事。

