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()
“This
is
2
”
end
def
do_1()
“This
is
1
”
end
def
do_4()
“This
is
4
”
end
def
do_3()
“This
is
3
”
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。
system(“.ruby”)或者load 'another.rb'具体代码如下:
# 返回ls的输出
s=`ls`
cmd= "ls"
s= `#{cmd}`
# 返回true or false
s= system('ls')
cmd= 'ls'
s= system(cmd)
#返回输出
s= %x[uptime]
#用top进程替换当前ruby进程
exec "top"
cmd = 'top'
exec cmd
undefined是一个特殊值,通常用于指示变量尚未赋值。对未定义值的引用返回特殊值。其实大多数计算机语言,只有一个表示"无"的值,比如,C语言的NULL,Java语言的null,Python语言的None,Ruby语言的nil。
undefined
英 [ˌʌndɪˈfaɪnd] 美 [ˌʌndɪˈfaɪnd]
adj.
未阐明的未限定的
双语例句
1.As we shall not deal with algorithmic problems, we leave the term "efficient" undefined.
因为不讨论算法问题,我们对“有效”这一术语不作具体解释。
2.The money was lent for an undefined period of time.
这笔钱无限期借出。
3.An undefined prefix is in use.
使用了未定义的前缀。
4.Call to undefined function getmxrr.
是调用了未定义的函数。
5.Undefined elements can be included in an array literal by simply omitting a value between commas.
数组直接量中还可以存放未定义的元素,只要在逗号之间省去该元素的值就可以了。
扩展资料:
说明
一个特殊值,通常用于指示变量尚未赋值。对未定义值的引用返回特殊值“未定义”。类型定义代码 typeof(undefined) 返回未定义字符串。
当将“未定义”转换为字符串时,它转换为空字符串。
“未定义”值与特殊值null(空)相似。事实上,当使用相等运算符对null(空)和“未定义”进行比较时,它们的比较结果为相等。
参考资料来源:百度百科:undefined(程序语句)