Ruby:单例类是否真的拥有匿名类?

时间:2018-11-17 11:00:04

标签: ruby singleton

Programming Ruby 1.9&2.0 一书的 24.2 Singletons 一章中,给出了以下代码:

animal = "cat"
def animal.speak
  puts "The #{self} says miaow"
end

并解释为:“当我们为“ cat ”对象定义单例方法时,Ruby创建了一个新的匿名类,并在该类中定义了 speak 方法。这个匿名类称为单类(有时称为本征类)。”

不幸的是,我无法验证Ruby(2.5.1)确实创建了自己的匿名类:

str = "a string"                 # => "a string"
[str, str.object_id]             # => ["a string", 47279316765840]
[str.class, str.class.object_id] # => [String, 47279301115420]

def str.greet
  "hello"
end                              # => :greet

str.greet                        # => "hello"

[str, str.object_id]             # => ["a string", 47279316765840]
[str.class, str.class.object_id] # => [String, 47279301115420]

从上面可以看出,定义单例方法 greet 后, str 的类不会更改:它仍显示为 String 具有相同的object_id 47279301115420。

那么,匿名类在哪里?

1 个答案:

答案 0 :(得分:2)

str = "a string"                 # => "a string"
[str, str.object_id]             # => ["a string", 47279316765840]
[str.class, str.class.object_id] # => [String, 47279301115420]

def str.greet
  "hello"
end                              # => :greet

str.greet                        # => "hello"
当您问str.class或查找祖先链(str.class.ancestors)时,

Ruby会隐藏本征类。但是,您可以使用<<

在检查其类之后,通过返回self来获取对eigenclass的引用
str_class = class << str
  self
end
# => #<Class:#<String:0x007fbba28b3f20>>

str_class.instance_methods(false) #=> [:greet] # the singleton method you defined becomes the instance method of this eigenclass. :)

str_class.ancestors
[#<Class:#<String:0x007fbba28b3f20>>, String, Comparable, Object, Kernel, BasicObject]