【问题标题】:Deep into Ruby class_eval and instance_eval深入 Ruby class_eval 和 instance_eval
【发布时间】:2017-04-22 17:21:12
【问题描述】:

class_evalinstance_eval 在定义方法等情况下是完全可以预测的。我也了解类的实例和类的单例(又名 eigenclass)之间的区别。

但是

我无法弄清楚唯一的事情如下: 比方说,出于某种战略目的,我们想让现有的类成为单例。

class A; end
class B; end

A.class_eval do
  private :new
end

B.instance_eval do
  private :new
end

在这两种情况下都得到了

NameError: undefined method 'new' for class
Did you mean?  new

是的,我的意思就是这个方法。

此外,这两个变体给出相同的结果,例如 self 在两种情况下都指向类对象

A.class_eval do
  class << self
    private :new
  end
end

A.new
=> NoMethodError: private method 'new' called for A:Class

B.instance_eval do
  class << self
    private :new
  end
end

B.new
=> NoMethodError: private method 'new' called for B:Class

怎么会?有人能解释一下吗?

【问题讨论】:

  • Ruby 中的类中的 new 实际上是使用 initialize 定义的。尝试用:initialize替换:new
  • @casraf 这不正确。 new 由 Class(所有类的超类)定义,并做了两件事(来自 the docs):“调用 allocate 以创建 class 类的新对象,然后调用该对象的initialize 方法,将其传递args。每当使用.new 构造对象时,最终都会调用此方法。”当您在类中定义(覆盖)initialize 时,它不会定义或更改 new,并且 new 可以像任何其他类方法一样被覆盖(尽管我想不出理由)。
  • 我的错。感谢您的澄清:)

标签: ruby instance-eval class-eval


【解决方案1】:

让我们来看看这里的自我:

class A
  puts self.inspect

  class << self
    puts self.inspect
  end
end

A.class_eval {
  puts self.inspect

  class << self
    puts self.inspect
  end
}

A.instance_eval{
  puts self.inspect

  class << self
    puts self.inspect
  end
}

我们得到以下输出:

A
#<Class:A>
A
#<Class:A>
A
#<Class:A>

class_eval 方法是为模块(以及类)定义的,并在模块(类)的上下文中进行评估。 instance_eval 方法在 BasicObject 的上下文中求值。在这些情况下,这两个(实际上是三个)似乎是同一件事。

但是,我知道如果方法是在 eval 块内创建,那么 class_eval 会创建实例方法,而 instance_eval 会创建类方法。已经有一篇关于该观察的优秀帖子:

【讨论】:

    猜你喜欢
    • 2011-05-23
    • 1970-01-01
    • 2012-05-05
    • 2011-03-26
    • 1970-01-01
    • 2011-03-11
    • 2011-03-02
    • 2011-04-01
    • 2010-10-28
    相关资源
    最近更新 更多