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

面试题 相关文章推荐
Java面试题及答案
Sep 08 面试题
C/C++程序员常见面试题二
Nov 19 面试题
为什么如下的代码int a=100,b=100;long int c=a * b;不能工作
Nov 29 面试题
如何在Oracle中查看各个表、表空间占用空间的大小
Oct 31 面试题
.NET面试题:什么是反射
Sep 30 面试题
TCP/IP中的TCP和IP分别承担什么责任
Apr 21 面试题
网络体系结构及协议的定义
Mar 13 面试题
路由表示做什么用的?在linux环境中怎么来配置一条默认路由?
Jun 07 面试题
什么是静态路由?什么是动态路由?各自的特点是什么?
Sep 16 面试题
Why do we need Unit test
Jan 03 面试题
传统软件工程与面向对象的软件工程有什么区别
May 31 面试题
如何利用XMLHTTP检测URL及探测服务器信息
Nov 10 面试题
介绍一下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验证码(支持中文)
2007/02/14 PHP
php引用地址改变变量值的问题
2012/03/23 PHP
PHP的Socket通信之UDP通信实例
2015/07/02 PHP
PHP共享内存用法实例分析
2016/02/12 PHP
PHP笛卡尔积实现算法示例
2018/07/30 PHP
Laravel框架实现调用百度翻译API功能示例
2019/05/30 PHP
javascript中创建对象的三种常用方法
2010/12/30 Javascript
js网页侧边随页面滚动广告效果实现
2011/04/14 Javascript
web性能优化之javascript性能调优
2012/12/28 Javascript
关于JS Lodop打印插件打印Bootstrap样式错乱问题的解决方案
2016/12/23 Javascript
微信JSAPI支付操作需要注意的细节
2017/01/10 Javascript
浅析vue component 组件使用
2017/03/06 Javascript
Form表单上传文件(type="file")的使用
2017/08/03 Javascript
详解vue-cli 构建Vue项目遇到的坑
2017/08/30 Javascript
在vue项目中集成graphql(vue-ApolloClient)
2018/09/08 Javascript
laypage.js分页插件使用方法详解
2019/07/27 Javascript
使用scrapy实现爬网站例子和实现网络爬虫(蜘蛛)的步骤
2014/01/23 Python
Python生成不重复随机值的方法
2015/05/11 Python
python机器学习之KNN分类算法
2018/08/29 Python
Python饼状图的绘制实例
2019/01/15 Python
python接口自动化(十七)--Json 数据处理---一次爬坑记(详解)
2019/04/18 Python
详解Python3 中的字符串格式化语法
2020/01/15 Python
tensorflow2.0的函数签名与图结构(推荐)
2020/04/28 Python
全球最大的在线橄榄球商店:Lovell Rugby
2018/05/20 全球购物
会计找工作求职信范文
2013/12/09 职场文书
预备党员党课思想汇报
2014/01/13 职场文书
元旦获奖感言
2014/03/08 职场文书
创意广告词
2014/03/17 职场文书
社区领导班子四风问题原因分析及整改措施
2014/09/28 职场文书
2015年公务员工作总结
2015/04/24 职场文书
小区环境卫生倡议书
2015/04/29 职场文书
干货!开幕词的写作方法
2019/04/02 职场文书
授权协议书范本(3篇)
2019/10/15 职场文书
HTML速写之Emmet语法规则的实现
2021/04/07 HTML / CSS
Java spring单点登录系统
2021/09/04 Java/Android
《黑岩★★射手 DAWN FALL》BD发售宣传CM公开
2022/04/04 日漫