设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 2479|回复: 8
打印 上一主题 下一主题

[RMVA发布] Monkeypatch 1.0

[复制链接]

Lv3.寻梦者

唯一的信徒

梦石
0
星屑
1665
在线时间
1357 小时
注册时间
2013-1-29
帖子
1637
跳转到指定楼层
1
发表于 2014-2-12 13:18:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
当年写了一个用class_eval的笨蛋Monkeypacth嗯
于是这次发到外站之后果断有触手帮忙改了>_<,果然我就是个渣
于是把最终版本放这里吧:
RUBY 代码复制
  1. #===============================================================================
  2. #  Monkeypatch v 0.5 by BakaCoder aka XXX
  3. #  rewritten by IceDragon
  4. #===============================================================================
  5. # monkeypatch <method_name (sym)> (&block)
  6. #===============================================================================
  7. proc do
  8. # Example
  9.   class Scene_Base
  10.  
  11.     patch :initialize do
  12.       puts "A Scene has been initialized!"
  13.     end
  14.  
  15.     patch :initialize, :before do
  16.       puts "Scene #{self.class.name} initializing"
  17.     end
  18.  
  19.   end
  20.  
  21.   class Something
  22.  
  23.     def sum
  24.       1 + 1
  25.     end
  26.  
  27.     patch :sum, :chain do |oldsum|
  28.       oldsum + 1
  29.     end
  30.  
  31.   end
  32. # End
  33. end
  34.  
  35. module MonkeyPatch
  36.  
  37.   def monkeypatch(sym, pos=:after, &block)
  38.     meth = instance_method(sym) # original method
  39.     define_method(sym, &block)
  40.     meth2 = instance_method(sym) # alias method
  41.     case pos
  42.     when :after
  43.       define_method(sym) do |*a, &b|
  44.         meth.bind(self).call(*a, &b)
  45.         meth2.bind(self).call(*a, &b)
  46.       end
  47.     when :before
  48.       define_method(sym) do |*a, &b|
  49.         meth2.bind(self).call(*a, &b)
  50.         meth.bind(self).call(*a, &b)
  51.       end
  52.     when :chain
  53.       define_method(sym) do |*a, &b|
  54.         meth2.bind(self).call(meth.bind(self).call(*a, &b), *a, &b)
  55.       end
  56.     end
  57.   end
  58.  
  59.   alias :patch :monkeypatch
  60.  
  61. end
  62.  
  63. class Module
  64.   include MonkeyPatch
  65. end

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

评分

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

查看全部评分

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


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

Lv3.寻梦者

○赛

梦石
0
星屑
1249
在线时间
1276 小时
注册时间
2013-1-22
帖子
2246

贵宾

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

点评

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

使用道具 举报

Lv2.观梦者

梦石
0
星屑
453
在线时间
343 小时
注册时间
2012-8-9
帖子
118
3
发表于 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(#换成@)
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
80
在线时间
362 小时
注册时间
2013-12-8
帖子
427
4
发表于 2014-2-13 23:17:17 | 只看该作者
强迫症再表示,L姐姐你第一行的patch拼错了

点评

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

龙→
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (版主)

…あたしは天使なんかじゃないわ

梦石
0
星屑
2208
在线时间
4033 小时
注册时间
2010-10-4
帖子
10779

开拓者贵宾

5
发表于 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
回复 支持 反对

使用道具 举报

Lv4.逐梦者 (版主)

百合控

梦石
0
星屑
6643
在线时间
1275 小时
注册时间
2013-8-21
帖子
3657

开拓者

6
发表于 2014-2-15 20:28:04 | 只看该作者
看到chain的时候做了一个猜想 然后试验了一下

果然
RUBY 代码复制
  1. class Sot
  2.   def met
  3.     p "done"
  4.   end
  5.  
  6.   patch :met, :chain do |old|
  7.     p "pre"
  8.     old
  9.     p "aft"
  10.   end
  11. end
  12.  
  13. Sot.new.met
  14. #"done"
  15. #"pre"
  16. #"after"
萌新瑟瑟发抖
看到我请叫我去干活
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (版主)

…あたしは天使なんかじゃないわ

梦石
0
星屑
2208
在线时间
4033 小时
注册时间
2010-10-4
帖子
10779

开拓者贵宾

7
发表于 2014-2-16 12:05:57 | 只看该作者
本帖最后由 taroxd 于 2014-2-16 12:16 编辑
余烬之中 发表于 2014-2-15 20:28
看到chain的时候做了一个猜想 然后试验了一下

果然class Sot


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

这个方法相当于

RUBY 代码复制
  1. alias new_name old_name
  2. def old_name(*args, &block)
  3.   old_value = new_name(*args, &block)
  4.   # do something with old_value
  5. end


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

比如说
RUBY 代码复制
  1. class << BattleManager
  2.   patch :process_escape, :chain do |success|  # success 表示逃跑是否成功
  3.     @escape_ratio -= 0.1 unless success    # 如果没有成功,不改变下一次逃跑的成功率 (原方法会增加0.1)
  4.     success                # 不改变原方法的返回值
  5.   end
  6. end
回复 支持 反对

使用道具 举报

Lv4.逐梦者 (版主)

百合控

梦石
0
星屑
6643
在线时间
1275 小时
注册时间
2013-8-21
帖子
3657

开拓者

8
发表于 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
萌新瑟瑟发抖
看到我请叫我去干活
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (版主)

…あたしは天使なんかじゃないわ

梦石
0
星屑
2208
在线时间
4033 小时
注册时间
2010-10-4
帖子
10779

开拓者贵宾

9
发表于 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
回复 支持 反对

使用道具 举报

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

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-12-22 12:59

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表