查看: 2810|回复: 8

[RMVA发布] Monkeypatch 1.0

[复制链接]

唯一的信徒

梦石
0
星屑
1697
在线时间
1359 小时
注册时间
2013-1-29
回帖
1537
发表于 2014-2-12 13:18:14 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
当年写了一个用class_eval的笨蛋Monkeypacth嗯
于是这次发到外站之后果断有触手帮忙改了>_<,果然我就是个渣
于是把最终版本放这里吧:
[pre lang="ruby" line="1"]#===============================================================================
#  Monkeypatch v 0.5 by BakaCoder aka XXX
#  rewritten by IceDragon
#===============================================================================
# monkeypatch <method_name (sym)> (&block)
#===============================================================================
proc do
# Example
  class Scene_Base

    patch :initialize do
      puts "A Scene has been initialized!"
    end

    patch :initialize, :before do
      puts "Scene #{self.class.name} initializing"
    end

  end

  class Something

    def sum
      1 + 1
    end

    patch :sum, :chain do |oldsum|
      oldsum + 1
    end

  end
# End
end

module MonkeyPatch

  def monkeypatch(sym, pos=:after, &block)
    meth = instance_method(sym) # original method
    define_method(sym, &block)
    meth2 = instance_method(sym) # alias method
    case pos
    when :after
      define_method(sym) do |*a, &b|
        meth.bind(self).call(*a, &b)
        meth2.bind(self).call(*a, &b)
      end
    when :before
      define_method(sym) do |*a, &b|
        meth2.bind(self).call(*a, &b)
        meth.bind(self).call(*a, &b)
      end
    when :chain
      define_method(sym) do |*a, &b|
        meth2.bind(self).call(meth.bind(self).call(*a, &b), *a, &b)
      end
    end
  end

  alias :patch :monkeypatch

end

class Module
  include MonkeyPatch
end[/pre]
使用说明啥的基本不需要了,反正就是
patch :method_name do
#TODO
end
不过据说有奇怪的bug._.?

评分

参与人数 1星屑 +7 收起 理由
taroxd + 7 十分感动,果断抄袭走

查看全部评分

『我只是一个正在潜心修炼的渣乐师罢了』
Dear Time\(^o^)/~


假如上面的图片挂了的话麻烦各位去发个帖 @ 一下 orzFly 让他修复 deartime

○赛

梦石
0
星屑
1254
在线时间
1276 小时
注册时间
2013-1-22
回帖
2078

贵宾

发表于 2014-2-12 13:20:52 | 显示全部楼层
于是看到了大大又发布我看不懂的高端东东.........还是膜拜吧…………
决定偷偷和大大搞好关系~

点评

LBQ
开发者工具不需要制作者看懂,只需要脚本师看懂即可  发表于 2014-2-12 13:28
回复

使用道具 举报

梦石
0
星屑
453
在线时间
343 小时
注册时间
2012-8-9
回帖
109
发表于 2014-2-13 16:36:34 | 显示全部楼层
强迫症表示 直接用before和after做方法名是不是好一点0 0

点评

LBQ
自己看兰触的。。。+method_name method_name+直接自定义语法过了...  发表于 2014-2-14 06:54
hello, world

有事情邮件联系 shuenhoy#gmail.com(#换成@)
回复

使用道具 举报

梦石
0
星屑
86
在线时间
362 小时
注册时间
2013-12-8
回帖
420
发表于 2014-2-13 23:17:17 | 显示全部楼层
强迫症再表示,L姐姐你第一行的patch拼错了

点评

LBQ
我错了还不行吗._.  发表于 2014-2-14 06:53
柍念作yang三声。

龙→
回复

使用道具 举报

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

发表于 2014-2-15 18:45:24 | 显示全部楼层
本帖最后由 taroxd 于 2014-2-15 19:26 编辑

总觉得想法相当类似……
http://rpg.blue/thread-347871-1-1.html

第39行果断学习了!这方法我怎么没想到呢……我原来是用instance_exec的,然后一直纠结于怎么传block参数……
这样return也可以用了……总之太感动了……

于是可耻的把第39行抄袭走了~ 嗯……

另外,暂时没发现奇怪的bug
回复

使用道具 举报

百合控

梦石
0
星屑
6548
在线时间
1275 小时
注册时间
2013-8-21
回帖
3522

开拓者

发表于 2014-2-15 20:28:04 | 显示全部楼层
看到chain的时候做了一个猜想 然后试验了一下

果然[pre lang="ruby" line="1"]class Sot
  def met
    p "done"
  end
  
  patch :met, :chain do |old|
    p "pre"
    old
    p "aft"
  end
end

Sot.new.met
#"done"
#"pre"
#"after"[/pre]
萌新瑟瑟发抖
看到我请叫我去干活
回复

使用道具 举报

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

发表于 2014-2-16 12:05:57 | 显示全部楼层
本帖最后由 taroxd 于 2014-2-16 12:16 编辑
余烬之中 发表于 2014-2-15 20:28
看到chain的时候做了一个猜想 然后试验了一下

果然class Sot


没有任何问题啊,原方法的返回值是‘done’

这个方法相当于

[pre lang="ruby" line="1"]
alias new_name old_name
def old_name(*args, &block)
  old_value = new_name(*args, &block)
  # do something with old_value
end
[/pre]

在方法的目标是返回一个值的时候,这个方法很有用处

比如说
[pre lang="ruby" line="1"]
class << BattleManager
  patch :process_escape, :chain do |success|  # success 表示逃跑是否成功
    @escape_ratio -= 0.1 unless success    # 如果没有成功,不改变下一次逃跑的成功率 (原方法会增加0.1)
    success                # 不改变原方法的返回值
  end
end
[/pre]
回复

使用道具 举报

百合控

梦石
0
星屑
6548
在线时间
1275 小时
注册时间
2013-8-21
回帖
3522

开拓者

发表于 2014-2-16 12:17:41 | 显示全部楼层
taroxd 发表于 2014-2-16 12:05
没有任何问题啊,原方法的返回值是‘done’

这个方法相当于

我知道
我的意思是 在调用chain后的新方法时 会先执行旧方法内容 而不是临时执行 【旧方法求值→新内容1→使用旧值→新内容2】
如果旧方法和新内容对一个公用的变量进行了操作 就有一定的危险性 (但是只要注意到了就没有问题)
而晴兰的语法糖是在执行前进行预编译(宏替换?) 所以是这样的【新内容1→旧方法→新内容2】

点评

LBQ
这个就是我说的奇怪的bug_(:з」∠)_,反正我是懒地解决了TAT(对不起  发表于 2014-2-17 12:33
这个monkeypatch也可以用两次完成 话说我那个和这边的实现方式本来就差不多  发表于 2014-2-16 12:44
嗯,目的不是返回值的方法本来就不应该用chain  发表于 2014-2-16 12:41
萌新瑟瑟发抖
看到我请叫我去干活
回复

使用道具 举报

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

发表于 2014-2-16 12:31:27 | 显示全部楼层
本帖最后由 taroxd 于 2014-2-16 12:35 编辑
余烬之中 发表于 2014-2-16 12:17
我知道
我的意思是 在调用chain后的新方法时 会先执行旧方法内容 而不是临时执行 【旧方法求值→新内容1 ...


是啊,看出来了。

所以这里的参数是旧方法的返回值,而晴兰的语法糖是把old作为关键字代替旧方法

如果一定要吹毛求疵用旧方法也不是不行,在chain的时候用字符串的class_eval就行,不过比block形式麻烦多了,而且传字符串参数也不是很美观

其实我的想法是,如果要这么灵活地调用旧方法的话,还不如直接alias算了,这么弄也简单不了多少。所以我没有实现这个功能

话说,如果可以的话,用Ruby2.0的prepend功能也是个很好的解决方案,直接用super代原方法,可惜这里是1.9

点评

但是如果有人把这个patch拿去用的话 就有必要提醒一下了括弧笑  发表于 2014-2-16 12:35
我只是说一下罢了 其实你那个可以先do_before再do_after最后结果应该就是pre done after  发表于 2014-2-16 12:34
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部