赞 | 68 |
VIP | 397 |
好人卡 | 580 |
积分 | 22 |
经验 | 311270 |
最后登录 | 2022-3-9 |
在线时间 | 4033 小时 |
Lv3.寻梦者 (版主) …あたしは天使なんかじゃないわ
- 梦石
- 0
- 星屑
- 2208
- 在线时间
- 4033 小时
- 注册时间
- 2010-10-4
- 帖子
- 10779
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 taroxd 于 2014-12-16 17:45 编辑
曾经看到有人吐槽说,要是ruby有个关键字 def+ 之类的,可以直接在方法后面加东西就不用alias了。
于是闲着蛋疼写了类似的东西=。=
如果有什么bug的话求回复~
=begin 作者:Taroxd ------------------------------------------------------- 2014/2/14 更新 修改了def系列的实现方式,不会污染名称空间 def系列会同步方法的访问限制 修改了一些方法名 2014/2/15 更新 可以使用return,并支持block参数。 2014/2/18 更新 添加def_chain,彻底抛弃alias。 def_chain可以完全替代以前的alias 2014/4/6 更新 添加了singleton_def系列,可以用来重定义类方法等 2014/8/27 更新 def_before 与 def_after 添加了 hook 参数 对顶层环境添加了 def 系列的支持 2014/10/08 更新 对 def_with 与 def_chain 同样添加了 hook 参数 2014/12/16 更新 重构代码,使之更加易于扩展。 增加了 def_after!, def_and, def_or, def_if, def_unless ------------------------------------------------------- 使用示例可以参考 https://rpg.blue/forum.php?mod=forumdisplay&action=list&fid=539#groupnav 里面有大量的使用示例 ------------------------------------------------------ =end module Taroxd end module Taroxd::Def # 导入 Singleton = Module.new { Object.send :include, self } Module.send :include, self # 获取方法的访问限制 def get_access_control(sym) return :public if public_method_defined? sym return :protected if protected_method_defined? sym return :private if private_method_defined? sym nil end template = lambda do |singleton| if singleton klass = 'singleton_class' get_method = 'method' define = 'define_singleton_method' else klass = 'self' get_method = 'instance_method' define = 'define_method' end %( def <name>(sym, hook = nil, &b) access = #{klass}.get_access_control sym old = #{get_method} sym if b #{define} sym, &b hook = #{get_method} sym end if hook.respond_to? :to_sym hook = hook.to_sym #{define} sym do |*args, &block| <pattern_sym> end elsif hook.respond_to? :call #{define} sym do |*args, &block| <pattern_call> end elsif hook.kind_of? UnboundMethod #{define} sym do |*args, &block| <pattern_unbound> end end #{klass}.send access, sym sym end ) end # 保存模板和替换 'hook(' 字符串的字符 template = {false => template.call(false), true => template.call(true)} # 替换掉 pattern 中的语法 gsub_pattern = lambda do |pattern, singleton| old = singleton ? 'old' : 'old.bind(self)' pattern.gsub('*', '*args, &block') .gsub(/old(\()?/) { $1 ? "#{old}.call(" : old } end # 存入代替 "hook(" 的字符串 template['sym'] = '__send__(hook, ' template['call'] = 'hook.call(' template['unbound'] = 'hook.bind(self).call(' # 获取定义方法内容的字符串 code = lambda do |name, pattern, singleton| pattern = gsub_pattern.call(pattern, singleton) template[singleton] .sub('<name>', name) .gsub(/<pattern_(\w+?)>/) { pattern.gsub('hook(', template[$1]) } end main = TOPLEVEL_BINDING.eval('self') # 定义 def_ 系列方法的方法 define_singleton_method :def_ do |name, pattern| name = "#{__method__}#{name}" module_eval code.call(name, pattern, false) Singleton.module_eval code.call("singleton_#{name}", pattern, true) main.define_singleton_method name, &Kernel.method(name) end # 实际定义 def_ 系列的方法 def_ :after, 'ret = old(*); hook(*); ret' def_ :after!, 'old(*); hook(*)' def_ :before, 'hook(*); old(*)' def_ :with, 'hook(old(*), *)' def_ :chain, 'hook(old, *)' def_ :and, 'old(*) && hook(*)' def_ :or, 'old(*) || hook(*)' def_ :if, 'hook(*) && old(*)' def_ :unless, '!hook(*) && old(*)' end
=begin
作者:Taroxd
-------------------------------------------------------
2014/2/14 更新
修改了def系列的实现方式,不会污染名称空间
def系列会同步方法的访问限制
修改了一些方法名
2014/2/15 更新
可以使用return,并支持block参数。
2014/2/18 更新
添加def_chain,彻底抛弃alias。
def_chain可以完全替代以前的alias
2014/4/6 更新
添加了singleton_def系列,可以用来重定义类方法等
2014/8/27 更新
def_before 与 def_after 添加了 hook 参数
对顶层环境添加了 def 系列的支持
2014/10/08 更新
对 def_with 与 def_chain 同样添加了 hook 参数
2014/12/16 更新
重构代码,使之更加易于扩展。
增加了 def_after!, def_and, def_or, def_if, def_unless
-------------------------------------------------------
使用示例可以参考 https://rpg.blue/forum.php?mod=forumdisplay&action=list&fid=539#groupnav
里面有大量的使用示例
------------------------------------------------------
=end
module Taroxd end
module Taroxd::Def
# 导入
Singleton = Module.new { Object.send :include, self }
Module.send :include, self
# 获取方法的访问限制
def get_access_control(sym)
return :public if public_method_defined? sym
return :protected if protected_method_defined? sym
return :private if private_method_defined? sym
nil
end
template = lambda do |singleton|
if singleton
klass = 'singleton_class'
get_method = 'method'
define = 'define_singleton_method'
else
klass = 'self'
get_method = 'instance_method'
define = 'define_method'
end
%(
def <name>(sym, hook = nil, &b)
access = #{klass}.get_access_control sym
old = #{get_method} sym
if b
#{define} sym, &b
hook = #{get_method} sym
end
if hook.respond_to? :to_sym
hook = hook.to_sym
#{define} sym do |*args, &block|
<pattern_sym>
end
elsif hook.respond_to? :call
#{define} sym do |*args, &block|
<pattern_call>
end
elsif hook.kind_of? UnboundMethod
#{define} sym do |*args, &block|
<pattern_unbound>
end
end
#{klass}.send access, sym
sym
end
)
end
# 保存模板和替换 'hook(' 字符串的字符
template = {false => template.call(false), true => template.call(true)}
# 替换掉 pattern 中的语法
gsub_pattern = lambda do |pattern, singleton|
old = singleton ? 'old' : 'old.bind(self)'
pattern.gsub('*', '*args, &block')
.gsub(/old(\()?/) { $1 ? "#{old}.call(" : old }
end
# 存入代替 "hook(" 的字符串
template['sym'] = '__send__(hook, '
template['call'] = 'hook.call('
template['unbound'] = 'hook.bind(self).call('
# 获取定义方法内容的字符串
code = lambda do |name, pattern, singleton|
pattern = gsub_pattern.call(pattern, singleton)
template[singleton]
.sub('<name>', name)
.gsub(/<pattern_(\w+?)>/) { pattern.gsub('hook(', template[$1]) }
end
main = TOPLEVEL_BINDING.eval('self')
# 定义 def_ 系列方法的方法
define_singleton_method :def_ do |name, pattern|
name = "#{__method__}#{name}"
module_eval code.call(name, pattern, false)
Singleton.module_eval code.call("singleton_#{name}", pattern, true)
main.define_singleton_method name, &Kernel.method(name)
end
# 实际定义 def_ 系列的方法
def_ :after, 'ret = old(*); hook(*); ret'
def_ :after!, 'old(*); hook(*)'
def_ :before, 'hook(*); old(*)'
def_ :with, 'hook(old(*), *)'
def_ :chain, 'hook(old, *)'
def_ :and, 'old(*) && hook(*)'
def_ :or, 'old(*) || hook(*)'
def_ :if, 'hook(*) && old(*)'
def_ :unless, '!hook(*) && old(*)'
end
|
评分
-
查看全部评分
|