2010-02-27 95 views
60

在Ruby中,我可以定义一个方法foo =(巴):在Ruby中,如何检查方法“foo =()”是否已定义?

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 =”,以便它被解析并正确地传递给定义的?运营商。

回答

104

问题是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 
+0

谢谢!这解决了我的问题。我仍然很想知道是否有办法逃脱foo =这样它可以被定义为馈送?但至少现在我可以继续前进。 – 2010-02-27 19:24:24

+1

这里的问题是'foo ='总是用在赋值中,所以如果你测试了'defined',Ruby会返回''assignment''? foo()'(查看更新的答案)。 – molf 2010-02-27 19:40:50

32

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

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

+0

它是respond_to ?,而不是responds_to? – 0x4a6f4672 2012-07-30 15:42:22

+3

啊,Ruby核心库的拼写......'respond_to?','start_with?','end_with?'。 – Theo 2012-07-31 10:00:56

+1

http://stackoverflow.com/questions/5280556/why-does-ruby-use-respond-to-instead-of-responds-to对命名TL背后的选择有一个很好的解释; DR'you.knock if you.respond_to?(:敲)' – drewish 2014-10-23 19:03:25

相关问题