簡體   English   中英

instance_eval 和 class << self?

[英]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

這是我的理由:

  • ExampleClass的實例,因此 class 正文中的self指的是那個;
  • class << objself設置為給定塊中的任何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 << objself設置為給定塊中的任何obj ,在我的情況下是Class的實例,即Example (這可能是我錯的地方);

不, class << obj打開objsingleton 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM