Учитывая класс, посмотрите, имеет ли экземпляр метод (Ruby)
Я знаю в Ruby, что я могу использовать respond_to?
, чтобы проверить, имеет ли объект определенный метод.
Но, учитывая класс, как я могу проверить, имеет ли экземпляр определенный метод?
i.e, что-то вроде
Foo.new.respond_to?(:bar)
Но я чувствую, что должен быть лучший способ, чем создавать экземпляр нового экземпляра.
Ответы
Ответ 1
Я не знаю, почему все предлагают вам использовать instance_methods
и include?
когда method_defined?
делает работу
class Test
def hello; end
end
Test.method_defined? :hello #=> true
НОТА
В случае, если вы method_defined
на Ruby с другого языка OO, ИЛИ вы думаете, что method_defined
означает ТОЛЬКО методы, которые вы определили явно:
def my_method
end
тогда прочитайте это:
В Ruby свойство (атрибут) вашей модели также является в основном методом. Итак, method_defined?
также вернет true для свойств, а не только для методов.
Например:
Дан экземпляр класса с атрибутом String first_name
:
<instance>.first_name.class #=> String
<instance>.class.method_defined?(:first_name) #=> true
поскольку first_name
является одновременно атрибутом и методом (и строкой типа String).
Ответ 2
Вы можете использовать method_defined?
следующим образом:
String.method_defined? :upcase # => true
Намного проще, портативнее и эффективнее, чем instance_methods.include?
, кажется, предлагают все остальные.
Имейте в виду, что вы не будете знать, динамически реагирует ли класс на некоторые вызовы с помощью method_missing
, например, путем переопределения respond_to?
или с Ruby 1.9.2 путем определения respond_to_missing?
.
Ответ 3
На самом деле это не работает для объектов и классов.
Это делает:
class TestClass
def methodName
end
end
Таким образом, с данным ответом, это работает:
TestClass.method_defined? :methodName # => TRUE
Но это НЕ работает:
t = TestClass.new
t.method_defined? : methodName # => ERROR!
Поэтому я использую это для обоих классов и объектов:
Классы:
TestClass.methods.include? 'methodName' # => TRUE
Объекты:
t = TestClass.new
t.methods.include? 'methodName' # => TRUE
Ответ 4
Ответ на Учитывая класс, посмотрите, лучше ли экземпляр метода (Ruby). Очевидно, Ruby имеет этот встроенный модуль, и я как-то его пропустил. Мой ответ оставлен для справки, независимо.
классы Ruby отвечают на методы instance_methods
и public_instance_methods
. В Ruby 1.8 первое перечисляет все имена методов экземпляра в массиве строк, а второе ограничивает его общедоступными методами. Второе поведение - это то, что вы, скорее всего, захотите, так как respond_to?
также ограничивается общедоступными методами по умолчанию.
Foo.public_instance_methods.include?('bar')
В Ruby 1.9 эти методы возвращают массивы символов.
Foo.public_instance_methods.include?(:bar)
Если вы планируете делать это часто, вы можете расширить Module
, чтобы включить метод быстрого доступа. (Может показаться странным присвоить это 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, это было бы удобным местом для добавления логики для поиска как строк, так и символов.
Ответ 5
Не уверен, что это лучший способ, но вы всегда можете это сделать:
Foo.instance_methods.include? 'bar'
Ответ 6
Попробуйте Foo.instance_methods.include? :bar
Ответ 7
Если вы проверяете, может ли объект реагировать на ряд методов, вы можете сделать что-то вроде:
methods = [:valid?, :chase, :test]
def has_methods?(something, methods)
methods & something.methods == methods
end
methods & something.methods
присоединяется к двум массивам на их общих/согласованных элементах. something.methods включает в себя все методы, которые вы проверяете, это будет равным методам. Например:
[1,2] & [1,2,3,4,5]
==> [1,2]
так
[1,2] & [1,2,3,4,5] == [1,2]
==> true
В этой ситуации вы хотите использовать символы, потому что когда вы вызываете методы., он возвращает массив символов, и если вы использовали ["my", "methods"]
, он возвращал бы false.
Ответ 8
Я думаю, что что-то не так с method_defined?
в Rails. Это может быть непоследовательно или что-то в этом роде, поэтому, если вы используете Rails, лучше использовать что-то из attribute_method?(attribute)
.
"тестирование для method_defined? на классах ActiveRecord не работает до тех пор, пока экземпляр не станет вопросом о несогласованности.
Ответ 9
klass.instance_methods.include :method_name
или "method_name"
, в зависимости от версии Ruby, я думаю.
Ответ 10
class Foo
def self.fclass_method
end
def finstance_method
end
end
foo_obj = Foo.new
foo_obj.class.methods(false)
=> [:fclass_method]
foo_obj.class.instance_methods(false)
=> [:fclass_method]
Надеюсь, это поможет вам!
Ответ 11
В моем случае, работающем с ruby 2.5.3, следующие предложения сработали отлично:
value = "hello world"
value.methods.include? :upcase
Он вернет логическое значение true или false.