3

我是 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

4

2 回答 2

15

class_eval真的没有任何关系class << 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

请注意,如果 A 恰好是一个类(几乎)所有 ruby​​ 对象都有单例类,那么它们是唯一的类方法,您可以使用这两种语法中的任何一种来为它们定义方法。的优点class << obj主要是如果您一次性定义许多单例方法。

于 2011-03-22T13:31:59.070 回答
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 对象可用。

于 2011-03-22T14:04:35.330 回答