checking if a method is defined on the class

后端 未结 3 1452
有刺的猬
有刺的猬 2021-02-01 03:30

How do I check if a method is defined on some class directly, not by inheritance or by inclusion/extension? I want something like \'foo?\' in the following:

clas         


        
相关标签:
3条回答
  • 2021-02-01 03:49

    Use this:

    C.instance_methods(false).include?(:a)
    C.instance_methods(false).include?(:b)
    C.instance_methods(false).include?(:c)
    

    The method instance_methods return an Array of methods that an instance of this class would have. Passing false as first parameter returns only methods of this class, not methods of super classes.

    So C.instance_methods(false) returns the list of methods defined by C.

    Then you just have to check if that method is in the returned Array (this is what the include? calls do).

    See docs

    0 讨论(0)
  • 2021-02-01 03:52

    For objects you can use Object.respond_to?.

    Returns true if obj responds to the given method.

    For classes take a look at Module.instance_methods

    Returns an array containing the names of the public and protected instance methods in the receiver.

    0 讨论(0)
  • 2021-02-01 04:13

    Not exactly an answer to the question, but if you're reading this question, you might be interested in this, which uses .instance_methods(false)

    class Object
      # This is more or less how Ruby does method lookup internally
      def who_responds_to?(method, klass_ancestors = nil)
        if klass_ancestors.nil?
          return who_responds_to?(method, self.class.ancestors)
        end
    
        if klass_ancestors.empty?
          return nil
        end
    
        if klass_ancestors[0].instance_methods(false).include?(method)
          return klass_ancestors[0]
        end
    
        klass_ancestors.shift
    
        who_responds_to?(method, klass_ancestors)
      end
    end
    

    For example

    class Person
    end
    
    module Drummer
      def drum
      end
    end
    
    module Snowboarder
      def jump
      end
    end
    
    module Engineer
      def code
      end
    end
    
    class Bob < Person
      include Drummer
      include Snowboarder
      include Engineer
    
      def name
      end
    end
    
    puts "who responds to name"
    puts bob.who_responds_to?(:name)
    puts "\n"
    
    puts "who responds to code"
    puts bob.who_responds_to?(:code)
    puts "\n"
    
    puts "who responds to jump"
    puts bob.who_responds_to?(:jump)
    puts "\n"
    
    puts "who responds to drum"
    puts bob.who_responds_to?(:drum)
    puts "\n"
    
    puts "who responds to dance"
    puts bob.who_responds_to?(:dance)
    

    yields

    who responds to name
    Bob
    
    who responds to code
    Engineer
    
    who responds to jump
    Snowboarder
    
    who responds to drum
    Drummer
    
    who responds to dance
    [this line intentionally blank because return value is nil]
    
    0 讨论(0)
提交回复
热议问题