Ruby - 在 class 方法中引用 self

Ruby - reference of self in the class method

在 RubyMonk 上查看了这段代码:

 class Item
   def initialize(item)
     @item = item
   end
   def show
     puts "The item name is: #{self}"
   end
   def to_s
     "#{@item}"
   end
 end

 Item.new("potion").show

代码通过了,但是 self 变量的使用对我来说有点模糊。您可以在 show 方法中轻松地将 to_s 替换为 self 并获得相同的结果。有人可以解释一下这两种插值之间的区别,这里使用 why/how self 吗? 此外,没有方法 to_s,代码 returns 代理。这里定义to_s有什么意义呢?

字符串插值隐式调用对象的 to_s 方法。因此,当您在 Item 上定义 to_s 方法时,您 明确地 告诉该对象如何根据字符串表示自己。 self 在这种情况下使用,因为在 Item 对象的插值中隐式调用了 to_s。明确定义 to_s 告诉 Item 如何在字符串中呈现自身。

有关更多详细信息,请查看 this excellent post on explicit vs. implicit conversion methods.

虽然在您提供的示例中确实可以写 "The item name is: #{@item}",但情况并非总是如此。

正如 CDub 指出的那样,字符串插值隐式调用 to_s。如果一个对象没有定义 to_s 方法,Ruby returns 一个对象引用取而代之。在你给我们的例子中,写 "The item name is: #{@item}" 只有效,因为 String 实现了 to_s。如果没有,或者如果你使用 Item 来保存一个没有实现 to_s 的对象,你最终会得到该对象的引用。

现在了解在插值中使用 self@item 的区别。 self 引用当前对象。当您插入 self 时,您正在调用当前对象的 to_s 方法。当您插入 @item 时,您正在调用 @itemto_s 方法。在这个简单的例子中这不是问题,但让我们看一些更复杂的东西。假设我们有两个 类、ItemOtherItem(创意名称,我知道)。

 class Item
   def initialize(item)
     @item = item
   end
   def show
     puts "The item name is: #{self}"
   end
   def to_s
     "I'm a chunky monkey!"
   end
 end

  class OtherItem
   def initialize(item)
     @otherItem = item
   end
   def to_s
     "#{@otherItem}"
   end
 end

在这种情况下,Itemshow 方法使用 self,所以如果我们要写:

Item.new(OtherItem.new("potion")).show

Ruby 会调用 Item.show,后者又会调用 self.to_s。由于 self 在该上下文中是一个 Item,我们的输出将是:

"The item name is: I'm a chunky monkey!"

但是,如果我们像这样重新定义 Item.show

def show
  puts "The item name is: #{@item}"
end

并尝试再次调用 Item.new(OtherItem.new("potion")).showItem.show 会调用 @item.to_s,并填写它,所以我们会得到:

"The item name is: potion"