RSS
热门关键字:  java  Ajax  JSP  JSF  Struts
当前位置 : 首页>Ruby>列表

在Ruby中对字符串和block求解

来源: 作者: 时间:2007-09-19 点击:

介绍

对包含代码的字符串和block求解,是我最钟爱的Ruby特性之一。Ruby提供了多种不同类型的求解方式;不过我最常用的是下面这些:eval、instance_evalclass_eval

Module.class_eval

使用Module类的class_eval(及其别名module_eval)方法,可以在一个类的定义或者module定义的上下文中对给定字符串或block进行求解。我们常常用class_eval来向类的定义中加入方法,或是包含其他的module。

klass = Class.new
klass.class_eval do
include ERB::Util

def encoded_hello
htnl_escape "Hello World"
end
end

klass.new.encoded_hello #=> Hello World

不使用class_eval也可以达到上面的效果,但是要牺牲代码的可读性。

klass = Class.new
klass.send :include, ERB::Util
klass.send :define_method, :encoded_hello do
html_escape "Hello World"
end
klass.send :public, :encoded_hello

klass.new.encoded_hello #=> Hello World

Object.instance_eval

使用Objectinstance_eval方 法,可以在一个类实例的上下文中对给定字符串或block进行求解。这是个功能强大的概念:你可以先在任何上下文中创建一块代码,然后在一个单独的对象实 例的上下文中对这块代码进行求解。为了设定代码执行的上下文,self变量要设置为执行代码时所在的对象实例,以使得代码可以访问对象实例的变量。

class Navigator
def initialize
@page_index = 0
end
def next
@page_index += 1
end
end
navigator = Navigator.new
navigator.next
navigator.next
navigator.instance_eval "@page_index" #=> 2
navigator.instance_eval { @page_index } #=> 2

与使用class_eval的示例类似,实例变量的值可以通过其他的方式获取,不过使用instance_eval是一种非常直观的做法。

Kernel.eval

使用Kerneleval方法可以在当前上下文中对一个字符串求解。可以选择为eval方法制定一个binding对象。如果给定了一个binding对象,求解的过程会在binding对象的上下文中执行。

hello = "hello world"
puts eval("hello") #=> "hello world"

proc = lambda { hello = "goodbye world"; binding }
eval("hello", proc.call) #=> "goodbye world"

扩展eval的上下文

第一次使用eval,我用它来创建了attr_init这个类方法。当时我发现我总是在重复下面代码中的模式:

def some_attribute
@some_attribute || = SomeClass.new
end

因此我决定创建一个类方法来封装上面的行为:

class << Object
def attr_init(name, klass)
define_method(name) { eval "@#{name} ||= #{klass}.new" }
end
end

记得当时我觉得这样调用eval是非常丑陋的做法,但那会儿我想不出更好的方式来实现这样的效果;因此我把代码贴到了博客中,等待别人的指摘;他们 很快就做出了回应,并给出下面的做法。一开始我并没有觉察这样做的好处,但是后来我意识到这个解法是非常出色的:它只需要调用一次eval方法,而不是在 每次进行方法定义时都去重新调用eval。

class << Object
def attr_init(name, klass)
eval "define_method(name) { @#{name} ||= #{klass}.new }"
end
end

这样优化的有趣之处在于:它需要求解更多的内容, 以达到提升运行效率的目的。从那时开始,我只在必要的时候才使用eval,而且我非常注意如何以更有效率的方式来使用eval。

在不同上下文中使用instance_eval

共5页: 上一页 1 [2] [3] [4] [5] 下一页
最新评论共有 0 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册
Google Adsense
相关文章