В Ruby, как проверить, установлен ли метод "foo =()"?

В Ruby я могу определить метод foo = (bar):

irb(main):001:0> def foo=(bar)
irb(main):002:1>   p "foo=#{bar}"
irb(main):003:1> end
=> nil

Теперь я хочу проверить, было ли это определено,

irb(main):004:0> defined?(foo=)
SyntaxError: compile error
(irb):4: syntax error, unexpected ')'
 from (irb):4
 from :0

Каков правильный синтаксис для использования здесь? Я предполагаю, что должен быть способ избежать "foo =", чтобы он разбирался и правильно передавался определенному? Оператор.

Ответ 1

Проблема заключается в том, что метод foo= предназначен для использования в назначениях. Вы можете использовать defined? следующим образом, чтобы узнать, что происходит:

defined? self.foo=()
#=> nil
defined? self.foo = "bar"
#=> nil

def foo=(bar)
end

defined? self.foo=()
#=> "assignment"
defined? self.foo = "bar"
#=> "assignment"

Сравните это с:

def foo
end

defined? foo
#=> "method"

Чтобы проверить, установлен ли метод foo=, вместо respond_to?:

respond_to? :foo=
#=> false

def foo=(bar)
end

respond_to? :foo=
#=> true

Ответ 2

Вы можете проверить, существует ли метод с помощью метода respond_to?, и вы передаете ему символ, например. bar.respond_to?(:foo=), чтобы узнать, имеет ли объект bar метод foo=. Если вы хотите узнать, реагируют ли экземпляры класса на метод, вы можете использовать method_defined? для класса (или модуля), например. Foo.method_defined?(:bar=).

defined? не является методом, а оператором, который возвращает описание операнда (или nil, если он не определен, поэтому он может использоваться в выражении if). Операндом может быть любое выражение, то есть константа, переменная, назначение, метод, вызов метода и т.д. Причина, по которой это не работает, когда вы делаете defined?(foo=), из-за круглых скобок, пропустить их и должны работать более или менее, как ожидалось. При этом defined? является довольно странным оператором, и никто не использует его для проверки существования методов.