什么是class_eval和class<<之间的区别班级名称?

时间:2011-03-22 12:53:56

标签: ruby class-eval

我是Ruby的首发。我发现这些都非常相似(在输出中),但我无法理解下面的上下文中的差异。例如,我有一个班级

class Say
  def self.hello
    puts "hello"
  end
end

可以像这样扩展

class << Say
  def hi
    puts "hi"
  end
end

也喜欢这个

Say.class_eval do
  def self.bye
    puts "bye"
  end
end

我应该何时使用<<以及何时使用class_eval

2 个答案:

答案 0 :(得分:14)

class_evalclass << className没有任何关系。

A.class_eval do
   ...
end

相当于

class A
  ...
end

有一些差异。 class_eval使用一个块(或一个字符串,但暂时忽略它),这意味着它将关闭包含的词法范围。换句话说,您可以使用周围范围内的局部变量。公共类块引入了一个全新的范围。同样,您可以创建块并将其传递给许多不同的class_eval,并且块的主体将在您调用class_eval的类的上下文中执行。

class << className打开className的单例类,允许您定义类方法。

class << A
  def foo
    ...
  end
end

相同
def A.foo
  ...
end

注意它们是oly类方法,如果A碰巧是一个类(几乎),ruby中的所有对象都有单例类,你可以使用这两种语法中的任何一种为它们定义方法。 class << obj的优点主要在于您可以一次定义多个单例方法。

答案 1 :(得分:1)

正如已经说过的,class_eval与

没什么关系
class <<self

即使他们似乎在你的例子中做了同样的事情(虽然效果相似但它没有做同样的事情,但存在细微差别)。

这是另一个使用第二种形式更清晰的例子:

class A

end


a = A.new
b = A.new

class <<b
  def say_hi
    puts "Hi !"
  end
end


b.say_hi # will print "Hi !"
a.say_hi # will raise an undefined method

a和b都是同一个A类的对象,但是我们在b的元类中添加了一个方法,所以方法say_hi只对b对象可用。