Синглтон-класс синглтон-класса BasicObject в Ruby

Это в основном "академический", но здесь это идет:

Согласно этой диаграмме собственного класса Ruby (слегка отредактировано):

Возможно неправильная диаграмма собственного класса Ruby

BasicObject.singleton_class.singleton_class.superclass является Class,

Однако, запустив это на интерпретаторе Ruby (Ruby v2.5.1), получается, что BasicObject.singleton_class.singleton_class.superclass является #<Class:Class> и не Class, Таким образом, диаграмма лежит или я что-то упустил?

Диаграмма получена от пользователя, с которым я общался на Ruby IRC во Freenode. Тем не менее, он был процитирован несколько раз для многих других пользователей, и он воспринимался как библия объектной модели Ruby.

1 ответ

Поведение интерпретатора Ruby имеет смысл, потому что:

  • Когда Child класс расширяет ParentRuby устанавливает его так, чтобы класс синглтона #<Class:Child> продолжается #<Class:Parent> также; а также
  • BasicObject.singleton_class это подкласс Class, так BasicObject.singleton_class.singleton_class будет подклассом #<Class:Class>

Проверка равенства:

BasicObject.singleton_class.singleton_class.superclass.equal?(Class.singleton_class)
#=> true

Это приводит к следующему вопросу - почему #<Class:BaseObject> простираться Class на первом месте? Следуя правилу выше, так как BaseObject не имеет суперкласса, то есть BaseObject.superclass является nil - логично было бы, чтобы у его синглтон-класса не было суперкласса.

Ответ в том, что #<Class:BaseObject> простирающийся Class обеспечивает согласованность в иерархии наследования, когда дело доходит до одноэлементных классов. Возьмите этот объект Ruby, например:

obj = "a string"

Хорошо известно, что вместо obj быть просто примером Stringмы можем рассматривать его как (единственный) экземпляр своего собственного одноэлементного класса, который, в свою очередь, является подклассом String, То есть:

obj.class.equal?(obj.singleton_class.superclass)
#=> true

Кажется логичным, что то же самое должно относиться и к экземплярам классов. Но это не так, потому что это противоречит упомянутому выше правилу, когда суперкласс одноэлементного класса Child класс является единственным классом его Parent учебный класс.

class Foo; end

Foo.class
#=> Class

Foo.singleton_class.superclass
#=> #<Class:Object>      <-- not equal to Class!

# because:
Foo.superclass
#=> Object

Но можно разрешить это противоречие, поместив Class в верхней части иерархии наследования синглтон-классов:

Foo.singleton_class.superclass
#=> #<Class:Object>

Foo.singleton_class.superclass.superclass
#=> #<Class:BasicObject>

Foo.singleton_class.superclass.superclass.superclass
#=> Class

Таким образом, хотя Foo.singleton_class.superclass не равно Foo.class, пройдя по цепочке наследования, она в конце концов доберется...

Другие вопросы по тегам