85

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

4

2 回答 2

137

问题是该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
于 2010-02-27T18:56:35.790 回答
44

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

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

于 2010-06-04T17:52:58.607 回答