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如何设置和取得Cookie值
Jun 30 面试题
怎样比较两个类型为String的字符串
Aug 17 面试题
请问如下代码执行后a和b的值分别是什么
May 05 面试题
利用异或运算实现两个无符号数的加法运算
Dec 20 面试题
在什么时候需要使用"常引用"
Dec 31 面试题
.NET里面如何取得当前的屏幕分辨率
Dec 06 面试题
可靠的数据流传输TCP
Mar 15 面试题
简单叙述一下MYSQL的优化
May 09 面试题
如果重写了对象的equals()方法,需要考虑什么
Nov 02 面试题
Java如何支持I18N?
Oct 31 面试题
一套Delphi的笔试题一
Feb 14 面试题
Java面试题冲刺第十五天--设计模式
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
农民和部队如何穿矿
2020/03/04 星际争霸
全国FM电台频率大全 - 29 青海省
2020/03/11 无线电
PHP 数据结构 算法描述 冒泡排序 bubble sort
2011/07/10 PHP
php函数实现判断是否移动端访问
2015/03/03 PHP
分享PHP守护进程类
2015/12/30 PHP
php上传图片获取路径及给表单字段赋值的方法
2016/01/23 PHP
PHP pthreads v3使用中的一些坑和注意点分析
2020/02/21 PHP
一段实时更新的时间代码
2006/07/07 Javascript
抽出www.templatemonster.com的鼠标悬停加载大图模板的代码
2007/07/11 Javascript
Javascript中Eval函数的使用说明
2008/10/11 Javascript
javascript动态向网页中添加表格实现代码
2014/02/19 Javascript
javascript + jquery实现定时修改文章标题
2014/03/19 Javascript
jquery超简单实现手风琴效果的方法
2015/06/05 Javascript
使用基于Node.js的构建工具Grunt来发布ASP.NET MVC项目
2016/02/15 Javascript
简单谈谈javascript中this的隐式绑定
2016/02/22 Javascript
阻止表单提交按钮多次提交的完美解决方法
2016/05/16 Javascript
TypeScript学习之强制类型的转换
2016/12/27 Javascript
javascript 初学教程及五子棋小程序的简单实现
2017/07/04 Javascript
Bootstrap开发中Tab标签页切换图表显示问题的解决方法
2018/07/13 Javascript
Taro UI框架开发小程序实现左滑喜欢右滑不喜欢效果的示例代码
2020/05/18 Javascript
jQuery实现滑动开关效果
2020/08/02 jQuery
Vue实现简单计算器
2021/01/20 Vue.js
用Python计算三角函数之atan()方法的使用
2015/05/15 Python
浅谈Python使用Bottle来提供一个简单的web服务
2017/12/27 Python
Python浅复制中对象生存周期实例分析
2018/04/02 Python
Python中的list与tuple集合区别解析
2019/10/12 Python
解析Python 偏函数用法全方位实现
2020/06/26 Python
H5 canvas实现贪吃蛇小游戏
2017/07/28 HTML / CSS
手把手教你实现一个canvas智绘画板的方法
2019/03/04 HTML / CSS
SKECHERS官方旗舰店:美国舒适运动休闲品牌
2017/12/22 全球购物
英国网上购买肉类网站:Great British Meat
2018/10/17 全球购物
群众路线问题查摆对照检查材料
2014/10/04 职场文书
医院志愿者活动总结
2015/05/06 职场文书
基层医务人员三严三实心得体会
2016/01/05 职场文书
python flask框架快速入门
2021/05/14 Python
Python使用PyYAML库读写yaml文件的方法
2022/04/06 Python