Given a class, see if instance has method (Ruby)

前端 未结 12 1807

I know in Ruby that I can use respond_to? to check if an object has a certain method.

But, given the class, how can I check if the instance has a certai

相关标签:
12条回答
  • 2020-12-12 12:57

    You can use method_defined? as follows:

    String.method_defined? :upcase # => true
    

    Much easier, portable and efficient than the instance_methods.include? everyone else seems to be suggesting.

    Keep in mind that you won't know if a class responds dynamically to some calls with method_missing, for example by redefining respond_to?, or since Ruby 1.9.2 by defining respond_to_missing?.

    0 讨论(0)
  • 2020-12-12 12:57

    Actually this doesn't work for both Objects and Classes.

    This does:

    class TestClass
      def methodName
      end
    end
    

    So with the given answer, this works:

    TestClass.method_defined? :methodName # => TRUE
    

    But this does NOT work:

    t = TestClass.new
    t.method_defined? : methodName  # => ERROR!
    

    So I use this for both classes and objects:

    Classes:

    TestClass.methods.include? 'methodName'  # => TRUE
    

    Objects:

    t = TestClass.new
    t.methods.include? 'methodName'  # => TRUE
    
    0 讨论(0)
  • 2020-12-12 12:59

    Not sure if this is the best way, but you could always do this:

    Foo.instance_methods.include? 'bar'
    
    0 讨论(0)
  • 2020-12-12 12:59

    I think there is something wrong with method_defined? in Rails. It may be inconsistent or something, so if you use Rails, it's better to use something from attribute_method?(attribute).

    "testing for method_defined? on ActiveRecord classes doesn't work until an instantiation" is a question about the inconsistency.

    0 讨论(0)
  • 2020-12-12 13:02

    Try Foo.instance_methods.include? :bar

    0 讨论(0)
  • 2020-12-12 13:03

    The answer to "Given a class, see if instance has method (Ruby)" is better. Apparently Ruby has this built-in, and I somehow missed it. My answer is left for reference, regardless.

    Ruby classes respond to the methods instance_methods and public_instance_methods. In Ruby 1.8, the first lists all instance method names in an array of strings, and the second restricts it to public methods. The second behavior is what you'd most likely want, since respond_to? restricts itself to public methods by default, as well.

    Foo.public_instance_methods.include?('bar')
    

    In Ruby 1.9, though, those methods return arrays of symbols.

    Foo.public_instance_methods.include?(:bar)
    

    If you're planning on doing this often, you might want to extend Module to include a shortcut method. (It may seem odd to assign this to Module instead of Class, but since that's where the instance_methods methods live, it's best to keep in line with that pattern.)

    class Module
      def instance_respond_to?(method_name)
        public_instance_methods.include?(method_name)
      end
    end
    

    If you want to support both Ruby 1.8 and Ruby 1.9, that would be a convenient place to add the logic to search for both strings and symbols, as well.

    0 讨论(0)
提交回复
热议问题