![](/img/trans.png)
[英]How to understand the difference between class_eval() and instance_eval()?
[英]Difference between instance_eval and class << self?
我似乎無法掌握這兩個“構造”之間的確切區別。 在我看來,下面的小腳本應該 output 相同的東西 3 次:
class Example
puts self
class << self
puts self
end
instance_eval do
puts self
end
end
但是,output 是:
Example
#<Class:Example>
Example
這是我的理由:
Example
是Class
的實例,因此 class 正文中的self
指的是那個;class << obj
將self
設置為給定塊中的任何obj
,在我的情況下是Class
的實例,即Example
(這可能是我錯的地方);instance_eval
在給定實例中運行該塊,因此,在我的情況下,它與將代碼直接放在 class 主體中的塊中幾乎相同。 My current guess is that class << self
inserts a ghost class between Example
and Class
and sets self to that, but the output of #<Class:Example>
is not confirming that at all.
那么我的理由有什么問題呢?
class << obj
將self
設置為給定塊中的任何obj
,在我的情況下是Class
的實例,即Example
(這可能是我錯的地方);
不, class << obj
打開obj
的singleton class 。 As you correctly pointed out, inside of a class declaration, self
refers to the class itself, so, in this case, the "inner" self
(ie the one being passed to puts
) refers to the singleton class of Example
.
在我看來, class << self
一直是 Ruby 中最令人討厭的語法位之一。 剛接觸該語言的人幾乎不知道它的含義,除了貨物崇拜約定,即使是那些非常熟悉該語言的人也對它與instance_method
的區別只有模糊的理解,因為兩者似乎非常相似。
下面是定義 class 方法的兩種不同方法的示例:
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
方法被定義,但沒有綁定到 class 本身:
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 中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.