Учитывая класс, посмотрите, имеет ли экземпляр метод (Ruby)

Я знаю в Ruby, что могу использовать respond_to? проверять, имеет ли объект определенный метод.

Но, учитывая класс, как я могу проверить, имеет ли экземпляр определенный метод?

т.е., что-то как

Foo.new.respond_to?(:bar)

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

219
задан Arslan Ali 23 June 2015 в 23:48
поделиться

6 ответов

Я не знаю, почему все предлагают использовать instance_methods и include? , когда method_defined? выполняет свою работу.

class Test
  def hello; end
end

Test.method_defined? :hello #=> true

ПРИМЕЧАНИЕ

Если вы переходите на Ruby с другого объектно-ориентированного языка ИЛИ думаете, что method_defined означает ТОЛЬКО методы, которые вы явно определили с помощью:

def my_method
end

, тогда прочтите это:

In Ruby , свойство (атрибут) вашей модели также является методом. Итак, method_defined? также вернет true для свойств, не только для методов.

Например:

Для экземпляра класса с атрибутом String first_name :

<instance>.first_name.class #=> String

<instance>.class.method_defined?(:first_name) #=> true

, поскольку first_name является одновременно атрибутом и методом (и строкой типа String).

356
ответ дан 23 November 2019 в 04:10
поделиться

Не уверен, что это лучший способ, но вы всегда можете сделать так:

Foo.instance_methods.include? 'bar'
3
ответ дан 23 November 2019 в 04:10
поделиться

Вы можете использовать method_defined? следующим образом:

String.method_defined? :upcase # => true

Намного проще, портативнее и эффективнее, чем instance_methods.include?, который, похоже, предлагают все остальные.

Имейте в виду, что вы не узнаете, реагирует ли класс динамически на некоторые вызовы с method_missing, например, переопределив respond_to?, или, начиная с Ruby 1.9.2, определив respond_to_missing?.

45
ответ дан 23 November 2019 в 04:10
поделиться

Попробовать Foo.instance_methods.include? : bar

5
ответ дан 23 November 2019 в 04:10
поделиться

Лучше ответить на вопрос « Для данного класса посмотреть, есть ли у экземпляра метод (Ruby) ». Судя по всему, в Ruby есть встроенная функция, и я ее как-то упустил. В любом случае мой ответ оставлен для справки.

Классы Ruby отвечают на методы instance_methods и public_instance_methods . В Ruby 1.8 первый перечисляет все имена методов экземпляра в массиве строк, а второй ограничивает его общедоступными методами. Вы, скорее всего, захотите второго поведения, поскольку response_to? по умолчанию также ограничивается общедоступными методами.

Foo.public_instance_methods.include?('bar')

В Ruby 1.9, однако эти методы возвращают массивы символов.

Foo.public_instance_methods.include?(:bar)

Если вы планируете делать это часто, вы можете расширить Модуль , включив в него метод быстрого доступа. (Может показаться странным назначать это Module вместо Class , но поскольку именно там живут методы instance_methods , лучше придерживаться этого шаблона .)

class Module
  def instance_respond_to?(method_name)
    public_instance_methods.include?(method_name)
  end
end

Если вы хотите поддерживать как Ruby 1.8, так и Ruby 1.9, это было бы удобным местом для добавления логики для поиска как строк, так и символов.

10
ответ дан 23 November 2019 в 04:10
поделиться

klass.instance_methods.include :method_name или "method_name", в зависимости от версии Ruby, я думаю.

2
ответ дан 23 November 2019 в 04:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: