在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 =”,以便将其解析并正确传递给已定义的?操作员。

Answers:


131

问题在于该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=分配总是使用赋值,因此"assignment"如果您进行测试,Ruby将返回defined? foo()(请参阅更新的答案)。
molf 2010年

41

您可以使用respond_to?方法检查方法是否存在,并向其传递符号,例如bar.respond_to?(:foo=),查看对象bar是否具有method foo=。如果您想知道某个类的实例是否响应某个方法,则可以method_defined?在该类(或模块)上使用它,例如Foo.method_defined?(:bar=)

defined?不是方法,而是返回操作数描述的运算符(如果未定义,则返回nil,这就是为什么可以在if语句中使用它的原因)。操作数可以是任何表达式,即常量,变量,赋值,方法,方法调用等。当您这样做时,它不起作用的原因defined?(foo=)是由于括号,请跳过它们,它应该可以工作更多或少于预期。话虽这么说,它defined?是一个非常奇怪的运算符,没有人使用它来测试方法的存在。


是response_to ?,不是respons_to ??
0x4a6f4672 2012年

3
啊,红宝石核心库的拼写... respond_to?start_with?end_with?
Theo 2012年

3
stackoverflow.com/questions/5280556/…对命名TL背后的选择有很好的解释; DRyou.knock if you.respond_to?(:knock)
乏味的2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.