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面试题及答案-编程题
Oct 14 面试题
几个人围成一圈的问题
Sep 26 面试题
八皇后问题,输出了所有情况,不过有些结果只是旋转了90度
Aug 15 面试题
一套C++笔试题面试题
Jun 06 面试题
SQL Server数据库笔试题和答案
Feb 04 面试题
上海中网科技笔试题
Feb 19 面试题
异步传递消息系统的作用
May 01 面试题
百度JavaScript笔试题
Jan 15 面试题
什么是GWT的Module
Jan 20 面试题
介绍一下Python下range()函数的用法
Nov 07 面试题
简单叙述一下MYSQL的优化
May 09 面试题
Java中的基本数据类型所占存储空间大小固定的吗
Feb 15 面试题
介绍一下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实现文本数据导入SQL SERVER
2015/05/17 PHP
PHP实现json_decode不转义中文的方法
2017/05/20 PHP
由prototype_1.3.1进入javascript殿堂-类的初探
2006/11/06 Javascript
火狐浏览器(firefox)下获得Event对象以及keyCode
2008/11/13 Javascript
javascript限制文本框只允许输入数字(曾经与现在的方法对比)
2013/01/18 Javascript
js调用百度地图及调用百度地图的搜索功能
2015/09/07 Javascript
JavaScript常用基础知识强化学习
2015/12/09 Javascript
bootstrap按钮插件(Button)使用方法解析
2017/01/13 Javascript
Vue2单一事件管理组件通信
2017/05/09 Javascript
用React-Native+Mobx做一个迷你水果商城APP(附源码)
2017/12/25 Javascript
AngularJS实现动态切换样式的方法分析
2018/06/26 Javascript
详解vue移动端项目的适配(以mint-ui为例)
2018/08/17 Javascript
vue.js实现的全选与全不选功能示例【基于elementui】
2018/12/03 Javascript
node.js基于socket.io快速实现一个实时通讯应用
2019/04/23 Javascript
微信小程序 行的删除和增加操作实现详解
2019/09/29 Javascript
jQuery轮播图功能制作方法详解
2019/12/03 jQuery
微信小程序 button样式设置为图片的方法
2020/06/19 Javascript
python学习 流程控制语句详解
2016/06/01 Python
Python内置函数—vars的具体使用方法
2017/12/04 Python
python脚本生成caffe train_list.txt的方法
2018/04/27 Python
对命令行模式与python交互模式介绍
2018/05/12 Python
如何在Django项目中引入静态文件
2019/07/26 Python
Python空间数据处理之GDAL读写遥感图像
2019/08/01 Python
python运用pygame库实现双人弹球小游戏
2019/11/25 Python
白俄罗斯在线大型超市:e-dostavka.by
2019/07/25 全球购物
static全局变量与普通的全局变量有什么区别
2014/05/27 面试题
电脑教师的自我评价
2013/12/18 职场文书
《千年梦圆在今朝》教学反思
2014/02/24 职场文书
保密承诺书
2014/03/27 职场文书
小学生期末评语
2014/04/21 职场文书
大跃进口号
2014/06/16 职场文书
法学自荐信
2014/06/20 职场文书
高中家长意见怎么写
2015/06/03 职场文书
红色电影观后感
2015/06/18 职场文书
Mysql使用全文索引(FullText index)的实例代码
2022/04/03 MySQL
鲲鹏 CentOS 7 安装Python3.7
2022/05/11 Servers