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...

面试题 相关文章推荐
名词解释WEB SERVICE,SOAP,UDDI,WSDL,JAXP,JAXM;JSWDL开发包的介绍。
Oct 27 面试题
神路信息Java面试题目
Mar 31 面试题
描述内存分配方式以及它们的区别
Oct 15 面试题
编写strcpy函数
Jun 24 面试题
如何删除一个表里面的重复行
Jul 13 面试题
世界经理人咨询有限公司面试
Sep 23 面试题
什么是静态路由,其特点是什么?什么是动态路由,其特点是什么?
Jul 26 面试题
是否可以从一个static方法内部发出对非static方法的调用?
Aug 18 面试题
内部类的定义、种类以及优点
Oct 16 面试题
火山动力Java笔试题
Jun 26 面试题
J2EE模式面试题
Oct 11 面试题
Java面试题冲刺第十八天--Spring框架3
Aug 07 面试题
介绍一下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 clearstatcache()函数详解
2010/03/02 PHP
纯php生成随机密码
2015/10/30 PHP
php删除二维数组中的重复值方法
2018/03/12 PHP
PhpStorm 如何优雅的调试Hyperf的方法步骤
2019/11/24 PHP
greybox——不开新窗口看新的网页
2007/02/20 Javascript
javascript 一些用法小结
2009/09/11 Javascript
javascript 在firebug调试时用console.log的方法
2012/05/10 Javascript
jquery不会自动回收xmlHttpRequest对象 导致了内存溢出
2012/06/18 Javascript
js如何取消事件冒泡
2013/09/23 Javascript
js触发onchange事件的方法说明
2014/03/08 Javascript
JavaScript使用encodeURI()和decodeURI()获取字符串值的方法
2015/08/04 Javascript
jquery京东商城双11焦点图多图广告特效代码分享
2015/09/06 Javascript
浅谈javascript控制HTML5的全屏操控,浏览器兼容的问题
2016/10/10 Javascript
React中jquery引用的实现方法
2017/09/12 jQuery
javascript获取图片的top N主色值方法详解
2018/01/26 Javascript
Angular5集成eventbus的示例代码
2018/07/19 Javascript
react native 获取地理位置的方法示例
2018/08/28 Javascript
vue项目创建并引入饿了么elementUI组件的步骤
2019/04/11 Javascript
vue操作dom元素的3种方法示例
2020/09/20 Javascript
使用Python脚本生成随机IP的简单方法
2015/07/30 Python
Python的Twisted框架中使用Deferred对象来管理回调函数
2016/05/25 Python
利用Python正则表达式过滤敏感词的方法
2019/01/21 Python
python程序变成软件的实操方法
2019/06/24 Python
美国大型的健身社区和补充商店:Bodybuilding.com
2016/09/06 全球购物
北美Newegg打造的全球尖货海购平台:tt海购
2018/09/28 全球购物
意大利在线购买隐形眼镜网站:VisionDirect.it
2019/03/18 全球购物
JNI的定义
2012/11/25 面试题
Java编程面试题
2016/04/04 面试题
师生聚会感言
2014/01/26 职场文书
元旦联欢会策划方案
2014/06/11 职场文书
四风问题对照检查材料
2014/09/22 职场文书
党的群众路线对照检查材料范文
2014/09/24 职场文书
JS实现简单控制视频播放倍速的实例代码
2021/04/18 Javascript
Python超简单容易上手的画图工具库推荐
2021/05/10 Python
SQL写法--行行比较
2021/08/23 SQL Server
解决Mysql中的innoDB幻读问题
2022/04/29 MySQL