我是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
?
答案 0 :(得分:14)
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
注意它们是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对象可用。