我似乎无法掌握这两种“结构”之间的确切差异。在我看来,下面的小脚本应该输出三次相同的东西:
class Example
puts self
class << self
puts self
end
instance_eval do
puts self
end
end
然而,输出是:
Example
#<Class:Example>
Example
这是我的理由:
Example
是Class
的一个实例,因此类主体中的self
指的是那个; class << obj
将self
设置为给定块中的obj
,在我的情况下,Class
的实例为Example
(这是instance_eval
我可能错了); class << self
在给定的实例中运行块,因此,在我的情况下,它与将块中的代码直接放在类主体中几乎相同。我目前的猜测是,Example
在Class
和#<Class:Example>
之间插入一个幽灵等级,并将自设置为,但{{1}}的输出并未确认
那么我的理由是什么问题?
答案 0 :(得分:6)
class << obj
将self
设置为给定块中的obj
,在我的情况下,Class
的实例为Example
(这是class << obj
我可能错了);
不,obj
打开self
的单件类。正如您正确指出的那样,在类声明中,self
引用了类本身,因此,在这种情况下,“内部”puts
(即传递给Example
的那个)指的是{{1}}的单身类。
答案 1 :(得分:3)
在我看来,class << self
一直是Ruby中最令人讨厌的语法之一。除了货物崇拜惯例之外,对语言不熟悉的人几乎不知道这意味着什么,即使是那些非常熟悉语言的人也只是对instance_method
区别于什么的朦胧理解,因为这两者似乎是非常相似。
以下是定义类方法的两种不同方法的示例:
class Example
class << self
def class_def
:class_def
end
end
instance_eval do
def instance_def
:instance_def
end
end
end
您可以通过调用方法来检查这些是否有效:
puts Example.class_def.inspect
# => :class_def
puts Example.instance_def.inspect
# => :instance_def
区别在于您使用define_method
动态创建方法,因为instance_eval
版本的绑定似乎不正确:
class Example
class << self
define_method(:class_def) do
:class_def
end
end
instance_eval do
define_method(:instance_def) do
:instance_def
end
end
end
这导致定义了instance_def
方法,但没有绑定到类本身:
puts Example.class_def.inspect
# => :class_def
puts Example.instance_def.inspect
# => NoMethodError: undefined method ‘instance_def’ for Example:Class
创建动态方法的唯一可靠方法是使用class << self
。方法instance_def
似乎被创建并丢弃,因为即使在该块中,它也没有显示在Example.methods中。