Ruby 1.8 против 1.9: определение того, является ли синглтон-класс Ruby подклассом другого класса

Как уже упоминалось в ответе на предыдущий вопрос, B < A это самый простой способ определить, является ли класс подклассом другого. Однако, это, кажется, терпит неудачу в Ruby 1.8 (также REE 1.8), когда B является одноэлементным классом (т. е. собственным классом). Проиллюстрировать:

class A; end
class B < A; end

b = B.new

B.ancestors                         # => [B, A, Object, Kernel] (also BasicObject in 1.9)
(class << b; self; end).ancestors   # => [B, A, Object, Kernel] (also BasicObject in 1.9)

B < A                               # => true
(class << b; self; end) < A         # => true in 1.9; false in 1.8

Как видите, хотя A указан как предок синглтон-класса (class << b; self; end), это возвращает false когда вы проверяете, является ли его подкласс A в Ruby 1.8 (но правильно возвращает true в 1.9). После #superclass цепочка, чтобы показать, почему это так:

B.superclass
  # => A

(class << b; self; end).superclass
  # => B in 1.9
  # => singleton class of B in 1.8

(class << b; self; end).superclass.superclass
  # => A in 1.9
  # => singleton class of Class in 1.8

Кто-нибудь знает, это ошибка в 1.8, которая была исправлена ​​в 1.9 или, возможно, ожидаемое поведение, которое было целенаправленно изменено в 1.9? Я пытался найти упоминание или документацию по этой проблеме в другом месте, но не смог ничего найти.

И из-за этой проблемы кто-нибудь знает , как лучше всего проверить, что класс синглтона является подклассом A в Ruby 1.8? Я делал (class << b; self; end).ancestors.include?(A) в качестве обходного пути, хотя это технически не "правильно", так как список предков также содержит включенные модули.

1 ответ

Я бы предложил:

class Object; def metaclass; class << self; self; end; end; end

class A; end
class B < A; end

b = B.new

b.metaclass < A.metaclass || b.metaclass < A

Протестировано в Ruby 1.8, 1.9 и 2.0.

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