Question

Suppose class A is a descendant of class B. What is the best way to get the list (array of symbols, order insignificant) of all instance methods of A defined within B, i.e., instance methods of A that are defined on B or any of its descendant class? Example will be as follows. Where class hierarchy is as follows:

class C; def c; end end
class B < C; def b; end end
class D < B; def d; end end
class A < D; def a; end end

the instance methods of A within various classes would be:

A.instance_methods_within(Kernel) # =>  (Same as A.instance_methods)
A.instance_methods_within(C) # => [:a, :d, :b, :c]
A.instance_methods_within(B) # => [:a, :d, :b]
A.instance_methods_within(D) # => [:a, :d]
A.instance_methods_within(A) # => [:a]  (Same as A.instance_methods(false))
Was it helpful?

Solution 2

I believe you are looking for this:

class Class
  def instance_methods_within(klass)
    return self.instance_methods if klass == Object
    methods = []
    this = self
    while this != nil
      methods << this.instance_methods(false)
      break if this == klass
      this = this.superclass
    end

    return methods.flatten
  end
end

class C; def c; end end
class B < C; def b; end end
class D < B; def d; end end
class A < D; def a; end end

A.instance_methods_within(Object) # =>  (Same as A.instance_methods)
A.instance_methods_within(C) # => [:a, :d, :b, :c]
A.instance_methods_within(B) # => [:a, :d, :b]
A.instance_methods_within(D) # => [:a, :d]
A.instance_methods_within(A) # => [:a]  (Same as A.instance_methods(false))

I added the special case for Object as Object.instance_methods(false) yields [], thus the loop traversing upwards would not work well in that case. Updated to define the instance_methods_within class as an instance method of Class.

OTHER TIPS

This is my own solution.

class Class
  def instance_methods_within klass
    ancestors
    .select{|k| k <= klass}
    .inject([]){|a, k| a.concat(k.instance_methods(false))}
    .uniq
  end
end

Suggested by Marc-André Lafortune:

class Class
  def instance_methods_within klass
    ancestors
    .select{|k| k <= klass}
    .flat_map{|k| k.instance_methods(false)}
    .uniq
  end
end

I would like to present this:--

    class Class
      def instance_methods_within(klass = nil)
        imethods = instance_methods
        own_imethods = instance_methods(false)
        return imethods if [Object, Kernel, nil].include?(klass) || [BasicObject, nil].include?(klass.superclass)
        sc_imethods = klass.superclass.instance_methods
        own_imethods | (imethods - sc_imethods)
      end
    end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top