【问题标题】:In Ruby, how do I check if method "foo=()" is defined?在 Ruby 中,如何检查是否定义了方法“foo=()”?
【发布时间】:2011-01-21 20:31:05
【问题描述】:

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

【问题讨论】:

    标签: ruby syntax-error


    【解决方案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
    

    【讨论】:

    • 谢谢!这解决了我的问题。我仍然很想知道是否有办法逃脱 foo= 以便它可以被定义?但至少现在我可以继续前进了。
    • 这里的问题是foo= 总是用于赋值,所以如果你测试defined? foo(),Ruby 会返回"assignment"(见更新的答案)。
    【解决方案2】:

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

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

    【讨论】:

    • 是respond_to?,不是responds_to?
    • 啊,Ruby核心库的拼写...respond_to?start_with?end_with?
    • stackoverflow.com/questions/5280556/… 很好地解释了命名 TL 背后的选择;DR you.knock if you.respond_to?(:knock)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    • 1970-01-01
    • 1970-01-01
    • 2019-11-02
    相关资源
    最近更新 更多