Обнаружение того, что метод не был переопределен

Скажем, у меня есть следующие 2 класса:

class A
  def a_method
  end
end

class B < A
end

Можно ли обнаружить изнутри (экземпляра) класса B, что метод a_method только определен в суперклассе, поэтому не переопределяется в B?

Обновление: решение

Хотя я пометил ответ Чака как «принятый», позже Паоло Перрота заставил меня понять, что решение, по-видимому, может быть проще, и, вероятно, оно будет работать и с более ранними версиями Ruby.

Определение того, переопределен ли «a_method» в B:

B.instance_methods(false).include?("a_method")

И для методов класса мы используем singleton_methods аналогично:

B.singleton_methods(false).include?("a_class_method")

person mxgrn    schedule 08.11.2009    source источник


Ответы (3)


Если вы используете Ruby 1.8.7 или более позднюю версию, это легко сделать с помощью Method#owner/UnboundMethod#owner.

class Module
  def implements_instance_method(method_name)
    instance_method(method_name).owner == self
    rescue NameError
    false
  end
end
person Chuck    schedule 08.11.2009
comment
Очень круто, спасибо! Особенно счастлив после того, как увидел, что версия Ruby, о которой вы изначально упомянули, снизилась с 1.9 до 1.8.7 (которую я на самом деле использую). - person mxgrn; 09.11.2009
comment
Да, я немного запутался в этом. Сначала я подумал, что это работает с 1.8.7, затем увидел, что Method#owner не было в ri-документах 1.8.7, поэтому я изменил его на 1.9, затем я действительно проверил, существует ли этот метод в 1.8.7, и увидел, что он у меня есть. правильно с первого раза. Рад, что это помогает. - person Chuck; 09.11.2009

вы всегда можете перейти к следующему и посмотреть, определено ли оно там:

a = A.new

a.methods.include?(:method)
person ennuikiller    schedule 08.11.2009
comment
ОП спрашивает, как определить из класса B, переопределяет ли он метод или нет. Знание того, что класс A определяет метод, не говорит о том, переопределяет ли его класс B или нет. - person Carlos Lima; 08.11.2009
comment
Это хорошо, но как дополнительно обнаружить, что метод не (изначально) включен в методы экземпляра B? - person mxgrn; 08.11.2009
comment
ну, в b вы все еще можете увидеть, отвечает ли A на метод, если да, и B определяет тот же метод, то он, очевидно, переопределяет реализацию A - person ennuikiller; 08.11.2009
comment
@Carlos: ура, ты помог мне лучше сформулировать вопрос. Обновили заголовок. - person mxgrn; 08.11.2009
comment
@ennuikiller: остается вопрос, как увидеть из B, если B определяет этот метод, без разбора исходного кода... :) - person mxgrn; 08.11.2009

Имея объект b, который является экземпляром B, вы можете проверить, имеет ли непосредственный суперкласс b a_method:

b.class.superclass.instance_methods.include? 'a_method'

Обратите внимание, что проверка выполняется по имени метода, а не по символу или объекту метода.

«поэтому не переопределяется в B». Просто знать, что метод определен только в A, сложно, потому что вы можете определить метод для отдельных экземпляров A и B... так что я думаю, что это происходит трудно проверить, что a_method определен только для A, потому что вам придется собрать все подклассы и подэкземпляры в системе и протестировать их...

person Dafydd Rees    schedule 08.11.2009