Ruby 中的 instance_eval 方法

yufei       6 年, 3 月 前       965

首先,很抱歉,我在 Ruby 中的 class_eval 和 module_eval 方法 中漏了介绍另一个方法 instance_eval

其实,Ruby 中除了可以在 「 运行时 」 ( on-the-fly ) 向类或模块添加属性或方法之外,还可以向特定的实例添加方法,这种机制是通过 BasicObject#instance_eval 方法来实现的。

为什么没介绍呢 ?

因为这个方法根本不在 module 中。

添加方法

Ruby 中,当我们想要向实例添加方法时,我们可以使用 BasicObject#instance_eval 方法。此方法接受一个字符串或 「 块 」 作为参数

array_second = <<-RUBY
def second
  self[1]
end
RUBY

a = [1, 2, 3]
a.instance_eval(array_second)

a.second  # returns: 2

str = "ruby.devscoop.fr"
str.instance_eval do
  def /(delimiter)
    split(delimiter)
  end
end

str / '.' # returns: ["ruby", "devscoop", "fr"]

上面的代码中,调用 a.instance_eval(array_second) 方法会将 second 方法添加到变量 a 中 - 这是 Array 的一个实例 - 传递的字符串参数将会在实例 a 的上下文中执行

而将一个块作为参数调用 str.instance_eval 方法,会在实例 str 的上下文中运行块的内容 - strString 的一个实例。

访问内部变量

instance_eval 方法的另一个特性是它能够访问内部变量。

class User
  def initialize(email)
    @email = email
  end
end

u = User.new('no-reply@twle.cn')

u.instance_eval('@email')  # returns: "no-reply@twle.cn"
u.instance_eval { @email } # returns: "no-reply@twle.cn"

上面的代码中,我们将内部变量名 @email 的字符串形式作为参数传递给 u.instance_eval 来访问内部变量 @email

这是可能的,因为 instance_eval 是在接收器对象的上下文中执行的 - 在本例中是 u 变量

这意味着作为参数传递的所有代码都将在名为 u 的 User 实例的范围内执行

绕过方法访问控制

通过使用 instance_eval,可以从此外部调用给定对象的私有或受保护方法

class User
  def initialize(email)
    @email = email
  end

  private
  def secret_key
    'XX-XXXX-XXXX-XXXX'
  end
end

u = User.new('no-reply@twle.cn')

u.instance_eval('secret_key')  # returns: "XX-XXXX-XXXX-XXXX"
u.instance_eval { secret_key } # returns: "XX-XXXX-XXXX-XXXX"

上面的代码中,我们将内部方法名 secret_key 的字符串形式作为参数传递给 u.instance_eval 来访问内部方法 secret_key

目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.