У Ruby, як мені перевірити, чи визначено метод “foo = ()”?


81

У 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 =" такий, щоб він був проаналізований і переданий правильно визначеному? оператора.

Відповіді:


132

Проблема полягає в тому, що 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

Дякую! Це вирішує мою проблему. Мені все ще цікаво знати, чи є спосіб уникнути foo = такий, що його можна подати до визначеного? але принаймні зараз я можу рухатися далі.
Alex Boisvert

1
Проблема тут полягає в тому, що foo=вона завжди використовується в завданнях, тому Ruby повернеться, "assignment"якщо ви перевірите defined? foo()(див. Оновлену відповідь).
molf

43

Ви можете перевірити, чи існує метод, використовуючи respond_to?метод, і передати йому символ, наприклад, bar.respond_to?(:foo=)щоб перевірити, чи barмає об'єкт метод foo=. Якщо ви хочете знати, чи екземпляри класу відповідають на метод, який ви можете використовувати method_defined?для класу (або модуля), наприклад Foo.method_defined?(:bar=).

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


Це response_to ?, а не responds_to?
0x4a6f4672

3
Ах, написання основної бібліотеки Ruby , ... respond_to?, start_with?, end_with?.
Тео,

3
stackoverflow.com/questions/5280556/… має гарне пояснення вибору, що стоїть за іменованням TL; DRyou.knock if you.respond_to?(:knock)
drewish
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.