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.