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

Project1

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

[已经解决] 关于define_method的问题

[复制链接]

Lv3.寻梦者 (版主)

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

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

开拓者贵宾

跳转到指定楼层
1
发表于 2014-1-27 08:44:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 taroxd 于 2014-1-27 11:43 编辑

1. define_method 如何设置block参数?
2. define_method 如何设置参数的默认值?
3. block 里面如何使用 return ? 虽说似乎可以用next,但是……(见下文)

或者伸手伸的更直接点=。=
http://rpg.blue/thread-347871-1-1.html 求修改里面定义的 do_after 方法的 block 形式:
RUBY 代码复制
  1. class Module
  2.   def simple_alias(method, prefix = '_')
  3.     prefix *= 2 while method_defined?("#{prefix}#{method}")
  4.     alias_method "#{prefix}#{method}", method
  5.     "#{prefix}#{method}".to_sym
  6.   end
  7.  
  8.   def do_after(method, &block)
  9.     old_method = simple_alias(method)
  10.     define_method method do |*args|
  11.       send old_method, *args
  12.       instance_exec(*args, &block)
  13.     end
  14.   end
  15. end


1. 不能设置要重定义的方法的block参数(虽然说RGSS里面基本没什么方法要block参数的=。=)
2. 也不能设置默认参数
3. block里面直接return会出错,在alias方法的时候用next感觉怪蛋疼的。另外,在这个设定里面,能不能把block里面的return直接使要定义的方法return?
4. 要是block形式能改好我就把那个诡异的字符串形式扔掉了=。= 字符串形式完全拿来补充block做不到的功能,自己一次都没用过……

脚本渣表示求脚本大神帮助

Lv4.逐梦者 (版主)

百合控

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

开拓者

来自 5楼
发表于 2014-1-27 11:35:03 | 只看该作者
本帖最后由 余烬之中 于 2014-1-27 11:36 编辑
taroxd 发表于 2014-1-27 10:51
就是一个方便alias的货

alias b a


如果已有定义
RUBY 代码复制
  1. def okok(h,i)
  2.   # do something
  3.   yield(h,i) if block_given?
  4.   # do something
  5. end


然后你再alias
RUBY 代码复制
  1. alias :old_okok :okok
  2. def okok(h,i)
  3.   old_okok
  4.   haha_I_wanna_do_more # without args
  5. end


实现的话 可以是
RUBY 代码复制
  1. class I_AM_A_CLASS
  2.   # 已有的方法 带有区块
  3.   def okok(h, i = 1)
  4.     yield h, i
  5.   end
  6.  
  7.   # do_after的实现
  8.   def do_after(m, &add_on_block) # 方法名 新增的区块
  9.     eval("alias #{"_______#{m}"} #{m}") # 别名
  10.  
  11.     self.class.send :define_method, m do |*aaa, &block|
  12.                                        # *aaa是原方法的参数 &block是原方法的区块
  13.       method("_______#{m}").call(*aaa, &block) # 呼叫原方法
  14.       add_on_block.call # 呼叫新增的区块
  15.     end
  16.   end
  17. end
  18.  
  19. cl = I_AM_A_CLASS.new # 创建实例
  20. # 这里是在类中实现的 建议写在模块中 然后在类中include模块
  21.  
  22. cl.do_after(:okok){p true}
  23. # 重定义方法 a # 区块是新增的语句
  24.  
  25. cl.okok(3){|u,v| p u+v} # 呼叫a 区块是原a的区块
  26. #=> 4,true


萌新瑟瑟发抖
看到我请叫我去干活
回复 支持 反对

使用道具 举报

Lv4.逐梦者 (版主)

百合控

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

开拓者

2
发表于 2014-1-27 09:25:00 | 只看该作者
没办法在define_method定义的方法上加区块 因为define_method里不能有yield
可以通过过程实现

RUBY 代码复制
  1. class E
  2.   define_method(:me){|x , y=0, z = :block| # 设置参数
  3.     puts x,y # 第一步 输出x,y
  4.     if z.is_a?(Proc) # 如果给出了过程
  5.       r = z.call(1,2) # 呼叫过程 获取返回值
  6.       return if r = -1 # 如果返回的是特定的错误代码 return
  7.     end
  8.     puts y,x # 如果没有问题 输出y,x
  9.   }
  10. end
  11.  
  12. ex = E.new
  13. p = Proc.new{|a,b|
  14.   puts a + b # 过程第一步 返回a+b的值
  15.   next -1 # 返回
  16.   puts a - b # 如果没返回 输出a-b的值
  17. }
  18.  
  19. ex.me(3,4,p)
  20. #=> 3 4 3

点评

其实注释说明什么的都在链接里面……这里只打了代码没打注释,抱歉  发表于 2014-1-27 10:47

评分

参与人数 2星屑 +7 梦石 +1 收起 理由
Sion + 1 认可答案
taroxd + 7 我很赞同

查看全部评分

萌新瑟瑟发抖
看到我请叫我去干活
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (版主)

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

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

开拓者贵宾

3
 楼主| 发表于 2014-1-27 09:55:19 | 只看该作者
余烬之中 发表于 2014-1-27 09:25
没办法在define_method定义的方法上加区块 因为define_method里不能有yield
可以通过过程实现

非常谢谢!关于默认参数的问题,似乎是不用修改代码就可以解决了
关于block的问题,虽然演示的没错,但是不是我想要的。(我问题没问好)

我编辑了问题,写上了希望实现的代码。
这种实现传递block的方式似乎很难在这种方法里实现。
如果可以的话,能不能给一个修改的方式?不行就算了,总之一个问题解决了~ Thank you~

点评

我看了半天 终于弄懂了你想干什么……通过do_after(method,*args){block}操作 在已知方法后执行区块 是这样吗  发表于 2014-1-27 10:36
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (版主)

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

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

开拓者贵宾

4
 楼主| 发表于 2014-1-27 10:51:16 | 只看该作者
余烬之中 发表于 2014-1-27 09:25
没办法在define_method定义的方法上加区块 因为define_method里不能有yield
可以通过过程实现


就是一个方便alias的货

alias b a
def a(arg)
  b(arg)
  do_something_using_arg
end

简写成
do_after(:a) {|arg| do_something_using_arg }

但是上面的例子中,如果原来方法a是带有block参数的,那么这个do_after方法肯定会出问题
所以希望请教如何修改

回复 支持 反对

使用道具 举报

Lv3.寻梦者 (版主)

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

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

开拓者贵宾

6
 楼主| 发表于 2014-1-27 11:51:31 | 只看该作者
本帖最后由 taroxd 于 2014-1-27 11:52 编辑
余烬之中 发表于 2014-1-27 11:35
如果已有定义
def okok(h,i)
  # do something


非常感谢提供思路,至少让我知道了define_method 是可以直接带&block的
但是有问题,问题如下:

class I_AM_A_CLASS
  # 已有的方法 带有区块
  def okok(h, i = 1)
    yield h, i
  end

  # do_after的实现
  def do_after(m, &add_on_block) # 方法名 新增的区块
    eval("alias #{"_______#{m}"} #{m}") # 别名

    self.class.send :define_method, m do |*aaa, &block|
                                       # *aaa是原方法的参数 &block是原方法的区块
      method("_______#{m}").call(*aaa, &block) # 呼叫原方法
      add_on_block.call # 呼叫新增的区块
    end
  end
  
  def one
    1
  end
end

cl = I_AM_A_CLASS.new # 创建实例
# 这里是在类中实现的 建议写在模块中 然后在类中include模块

cl.do_after(:okok){p one}
# 重定义方法 a # 区块是新增的语句

cl.okok(3){|u,v| p u+v} # 呼叫a 区块是原a的区块
#=> undefined local variable or method `one' for main:Object (NameError)

不过我应该可以自己摸索出来了,谢啦~

点评

用instance_exec没有问题  发表于 2014-1-27 11:58
你可以吧(:okok){p one}改成(:okok){p cl.one} 这样应该不会报错  发表于 2014-1-27 11:56
因为调用的时候是在main下调用 区块的环境不是类的内部 所以我还是不建议使用区块 可以用字符串 然后eval(字符串)来取代add_on_block.call  发表于 2014-1-27 11:55
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (版主)

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

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

开拓者贵宾

7
 楼主| 发表于 2014-1-27 12:32:38 | 只看该作者

【新人乱改】自用的各种小脚本

余烬之中 发表于 2014-1-27 11:35
如果已有定义
def okok(h,i)
  # do something

RUBY 代码复制
  1. def do_after(method, &add)
  2.     old_method = simple_alias method
  3.     define_method method do |*args, &block|
  4.       send old_method, *args, &block
  5.       instance_exec *args, &add
  6.     end
  7.   end


虽然只是小小的改动,但至少在原来的方法中有block时不会报错了,但是没有把block传入instance_exec *args, &add(否则参数个数不定的时候会出问题),所以在 add 中不能调用方法的 block

总之非常感谢!!!
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-11-16 23:35

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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