Ruby如何实现动态方法调用


Posted in 面试题 onNovember 18, 2012
在Ruby中,有多种方法可以实现方法的动态调用。
1. 使用send方法
第一种实现动态方法调用是使用send方法,send方法在Object类中定义,方法的第一个参数是一个符号用来表示所要调用的方法,后面则是所调用方法需要的参数。
“This is a dog1″.send(:length) => 14
上面的代码中通过send方法去对一个字符串执行length操作,返回字符串的长度。

class TestClass
def hello(*args)
”Hello ” + args.join(‘ ‘)
end
end

a = TestClass.new
puts a.send :hello, “This”, “is”, “a”, “dog!”

执行结果为:
Hello This is a dog!

2. 使用Method类和UnboundMethod类
另一种实现动态方法调用是使用Object类的method方法,这个方法返回一个Method类的对象。我们可以使用call方法来执行方法调用。
test1 = “This is a dog1″.method(:length)
test1.call => 14

class Test
def initialize(var)
@var = var
end

def hello()
”Hello, @var = #{@var}”
end
end

k = Test.new(10)
m = k.method(:hello)
m.call #=> “Hello, @iv = 99″

l = Test.new(‘Grant’)
m = l.method(“hello”)
m.call #=> “Hello, @iv = Fred”

可以在使用对象的任何地方使用method对象,当调用call方法时,参数所指明的方法会被执行,这种行为有些像C语言中的函数指针。你也可以把method对象作为一个迭代器使用。
def square(a)
a*a
end

mObj = method(:square)
[1, 2, 3, 4].collect(&mObj) => [1 4 9 16]

Method对象都是和某一特定对象绑定的,也就是说你需要通过某一对象使用Method对象。你也可以通过UnboundMethod类创建对象,然后再把它绑定到某个具体的对象中。如果UnboundMethod对象调用时尚未绑定,则会引发异常。
class Double
def get_value
2 * @side
end

def initialize(side)
@side = side
end
end

a = Double.instance_method(:get_value) #返回一个UnboundMethod对象
s = Double.new(50)
b = a.bind(s)
puts b.call

执行结果为:
100

看下面一个更具体的例子:
class CommandInterpreter
def do_2() print “This is 2\n”; end
def do_1() print “This is 1\n”; end
def do_4() print “This is 4\n”; end
def do_3() print “This is 3\n”; end

Dispatcher = {
?2 => instance_method(:do_2),
?1 => instance_method(:do_1),
?4 => instance_method(:do_4),
?3 => instance_method(:do_3)
}

def interpret(string)
string.each_byte {|i| Dispatcher[i].bind(self).call }
end
end

interpreter = CommandInterpreter.new
interpreter.interpret(’1234′)

执行结果为:
This is 1
This is 2
This is 3
This is 4

3. 使用eval方法
我们还可以使用eval方法实现方法动态调用。eval方法在Kernel模块中定义,有多种变体如class_eval,module_eval,instance_eval等。Eval方法将分析其后的字符串参数并把这个字符串参数作为Ruby代码执行。
str = “Hello”
eval “str + ‘ World!’” => Hello World!

sentence = %q{“This is a test!”.length}
eval sentence => 15
当我们在使用eval方法时,我们可以通过eval方法的第二个参数指明eval所运行代码的上下文环境,这个参数可以是Binding类对象或Proc类对象。Binding类封装了代码在某一环境运行的上下文,可以供以后使用。
class BindingTest
def initialize(n)
@value = n
end

def getBinding
return binding() #使用Kernel#binding方法返回一个Binding对象
end
end

obj1 = BindingTest.new(10)
binding1 = obj1.getBinding
obj2 = BindingTest.new(“Binding Test”)
binding2 = obj2.getBinding

puts eval(“@value”, binding1) #=> 10
puts eval(“@value”, binding2) #=> Binding Test
puts eval(“@value”) #=> nil

可以看到上述代码中,@value在binding1所指明的上下文环境中值为10,在binding2所指明的上下文环境中值为Binding Test。当eval方法不提供binding参数时,在当前上下文环境中@value并未定义,值为nil。

Tags in this post...

面试题 相关文章推荐
可以在一个PHP文件里面include另外一个PHP文件两次吗
May 22 面试题
JAVA代码查错题
Oct 10 面试题
凌阳科技股份有限公司C++程序员面试题笔试题
Nov 20 面试题
几个数据库方面的面试题
Jul 01 面试题
试解释COMMIT操作和ROLLBACK操作的语义
Jul 25 面试题
铭万公司.net面试题笔试题
Jul 20 面试题
WEB控件及HTML服务端控件能否调用客户端方法?如果能,请解释如何调用?
Aug 25 面试题
linux面试题参考答案(9)
Jan 07 面试题
一些Unix笔试题和面试题
Jan 22 面试题
介绍一下Linux文件的记录形式
Apr 18 面试题
Linux的文件类型
Jul 05 面试题
J2EE面试题大全
Aug 06 面试题
介绍一下Ruby的特点
Jan 20 #面试题
JPA的优势都有哪些
Jul 04 #面试题
J2EE中的容器都包括哪些
Aug 21 #面试题
J2EE面试题
Mar 14 #面试题
J2EE包括哪些技术
Nov 25 #面试题
J2EE的优越性主要表现在哪些方面
Mar 28 #面试题
J2EE面试题集锦(附答案)
Aug 16 #面试题
You might like
PHP中去除换行解决办法小结(PHP_EOL)
2011/11/27 PHP
从零开始学YII2框架(六)高级应用程序模板
2014/08/20 PHP
php设计模式之备忘模式分析【星际争霸游戏案例】
2020/03/24 PHP
jQuery+ajax实现顶一下,踩一下效果
2010/07/17 Javascript
js中匿名函数的N种写法
2010/09/08 Javascript
js保存当前路径(cookies记录)
2010/12/14 Javascript
与jquery serializeArray()一起使用的函数,主要来方便提交表单
2011/01/31 Javascript
jQuery中deferred对象使用方法详解
2016/07/14 Javascript
Highcharts学习之数据列
2016/08/03 Javascript
通过npm引用的vue组件使用详解
2017/03/02 Javascript
js canvas实现适用于移动端的百分比仪表盘dashboard
2017/07/18 Javascript
浅谈express 中间件机制及实现原理
2017/08/31 Javascript
vue实现样式之间的切换及vue动态样式的实现方法
2017/12/19 Javascript
Three.js实现3D机房效果
2018/12/30 Javascript
详解jQuery-each()方法
2019/03/13 jQuery
vue+element table表格实现动态列筛选的示例代码
2021/01/14 Vue.js
[01:01:36]Optic vs paiN 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
Python的Django框架安装全攻略
2015/07/15 Python
Python 爬取携程所有机票的实例代码
2018/06/11 Python
Python3 合并二叉树的实现
2019/09/30 Python
python3 字符串知识点学习笔记
2020/02/08 Python
python实现俄罗斯方块游戏(改进版)
2020/03/13 Python
PyQt5通过信号实现MVC的示例
2021/02/06 Python
深入解析HTML5的IndexedDB索引数据库
2015/09/14 HTML / CSS
什么是数组名
2012/05/10 面试题
应届生.NET方向面试题
2015/05/23 面试题
中专毕业生自我鉴定
2013/11/21 职场文书
安全标准化实施方案
2014/02/20 职场文书
企业宣传方案
2014/03/04 职场文书
爱国卫生月活动总结范文
2014/04/25 职场文书
2015元旦标语横幅
2014/12/09 职场文书
2015年万圣节活动总结
2015/03/24 职场文书
2015年药店工作总结
2015/04/20 职场文书
2015年实习班主任工作总结
2015/04/23 职场文书
2015年预防青少年违法犯罪工作总结
2015/05/22 职场文书
日本动漫十大公认神作:第五现已全网禁播,《死亡笔记》在榜
2022/03/18 日漫