Project1
标题: 关于define_method的问题 [打印本页]
作者: taroxd 时间: 2014-1-27 08:44
标题: 关于define_method的问题 本帖最后由 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 形式:
class Module
def simple_alias( method, prefix = '_' )
prefix *= 2 while method_defined?( "#{prefix}#{method}" )
alias_method "#{prefix}#{method}" , method
"#{prefix}#{method}" .to_sym
end
def do_after( method, &block)
old_method = simple_alias( method)
define_method method do |*args|
send old_method, *args
instance_exec( *args, &block)
end
end
end
class Module
def simple_alias( method, prefix = '_' )
prefix *= 2 while method_defined?( "#{prefix}#{method}" )
alias_method "#{prefix}#{method}" , method
"#{prefix}#{method}" .to_sym
end
def do_after( method, &block)
old_method = simple_alias( method)
define_method method do |*args|
send old_method, *args
instance_exec( *args, &block)
end
end
end
1. 不能设置要重定义的方法的block参数(虽然说RGSS里面基本没什么方法要block参数的=。=)
2. 也不能设置默认参数
3. block里面直接return会出错,在alias方法的时候用next感觉怪蛋疼的。另外,在这个设定里面,能不能把block里面的return直接使要定义的方法return?
4. 要是block形式能改好我就把那个诡异的字符串形式扔掉了=。= 字符串形式完全拿来补充block做不到的功能,自己一次都没用过……
脚本渣表示求脚本大神帮助
作者: 余烬之中 时间: 2014-1-27 09:25
没办法在define_method定义的方法上加区块 因为define_method里不能有yield
可以通过过程实现
class E
define_method( :me ) { |x , y=0 , z = :block | # 设置参数
puts x,y # 第一步 输出x,y
if z.is_a ?( Proc ) # 如果给出了过程
r = z.call ( 1 ,2 ) # 呼叫过程 获取返回值
return if r = -1 # 如果返回的是特定的错误代码 return
end
puts y,x # 如果没有问题 输出y,x
}
end
ex = E.new
p = Proc .new { |a,b|
puts a + b # 过程第一步 返回a+b的值
next -1 # 返回
puts a - b # 如果没返回 输出a-b的值
}
ex.me ( 3 ,4 ,p )
#=> 3 4 3
class E
define_method( :me ) { |x , y=0 , z = :block | # 设置参数
puts x,y # 第一步 输出x,y
if z.is_a ?( Proc ) # 如果给出了过程
r = z.call ( 1 ,2 ) # 呼叫过程 获取返回值
return if r = -1 # 如果返回的是特定的错误代码 return
end
puts y,x # 如果没有问题 输出y,x
}
end
ex = E.new
p = Proc .new { |a,b|
puts a + b # 过程第一步 返回a+b的值
next -1 # 返回
puts a - b # 如果没返回 输出a-b的值
}
ex.me ( 3 ,4 ,p )
#=> 3 4 3
作者: taroxd 时间: 2014-1-27 09:55
余烬之中 发表于 2014-1-27 09:25
没办法在define_method定义的方法上加区块 因为define_method里不能有yield
可以通过过程实现
非常谢谢!关于默认参数的问题,似乎是不用修改代码就可以解决了
关于block的问题,虽然演示的没错,但是不是我想要的。(我问题没问好)
我编辑了问题,写上了希望实现的代码。
这种实现传递block的方式似乎很难在这种方法里实现。
如果可以的话,能不能给一个修改的方式?不行就算了,总之一个问题解决了~ Thank you~
作者: taroxd 时间: 2014-1-27 10:51
余烬之中 发表于 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方法肯定会出问题
所以希望请教如何修改
作者: 余烬之中 时间: 2014-1-27 11:35
本帖最后由 余烬之中 于 2014-1-27 11:36 编辑
taroxd 发表于 2014-1-27 10:51
就是一个方便alias的货
alias b a
如果已有定义
def okok( h,i)
# do something
yield ( h,i) if block_given?
# do something
end
def okok( h,i)
# do something
yield ( h,i) if block_given?
# do something
end
然后你再alias
alias :old_okok :okok
def okok( h,i)
old_okok
haha_I_wanna_do_more # without args
end
alias :old_okok :okok
def okok( h,i)
old_okok
haha_I_wanna_do_more # without args
end
实现的话 可以是
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
end
cl = I_AM_A_CLASS.new # 创建实例
# 这里是在类中实现的 建议写在模块中 然后在类中include模块
cl.do_after ( :okok ) { p true }
# 重定义方法 a # 区块是新增的语句
cl.okok ( 3 ) { |u,v| p u+v} # 呼叫a 区块是原a的区块
#=> 4,true
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
end
cl = I_AM_A_CLASS.new # 创建实例
# 这里是在类中实现的 建议写在模块中 然后在类中include模块
cl.do_after ( :okok ) { p true }
# 重定义方法 a # 区块是新增的语句
cl.okok ( 3 ) { |u,v| p u+v} # 呼叫a 区块是原a的区块
#=> 4,true
作者: taroxd 时间: 2014-1-27 11:51
本帖最后由 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)
不过我应该可以自己摸索出来了,谢啦~
作者: taroxd 时间: 2014-1-27 12:32
标题: 【新人乱改】自用的各种小脚本余烬之中 发表于 2014-1-27 11:35
如果已有定义
def okok(h,i)
# do something
def do_after( method, &add)
old_method = simple_alias method
define_method method do |*args, &block|
send old_method, *args, &block
instance_exec *args, &add
end
end
def do_after( method, &add)
old_method = simple_alias method
define_method method do |*args, &block|
send old_method, *args, &block
instance_exec *args, &add
end
end
虽然只是小小的改动,但至少在原来的方法中有block时不会报错了,但是没有把block传入instance_exec *args, &add(否则参数个数不定的时候会出问题),所以在 add 中不能调用方法的 block
总之非常感谢!!!
欢迎光临 Project1 (https://rpg.blue/)
Powered by Discuz! X3.1