Search code examples
rubymoduleoverridingmixins

Overriding instance methods of a class by mixing in a module


Given a class A and a module B, mixin the instance methods of B so that it overrides the correspnding instance methods of A.

module B
  def method1
    "B\#method1"
  end

  def method2
    "B\#method2"
  end
end

class A
  def method1
    "A\#method1"
  end

  def method2
    "A\#method2"
  end

  # include B    does not override instance methods!
  #              (module gets mixed into the superclass)
end

puts A.new.method1   # want it to print out "B#method1"
puts A.new.method2   # want it to print out "B#method2"

Solution

  • You could remove each of B's methods from A before including B.

    class A
      def method1
        "A\#method1"
      end
    
      def method2
        "A\#method2"
      end
    
      B.instance_methods(false).each { |method|
        remove_method(method) if instance_methods(false).include?(method)
      }
      include B
    end
    

    Or from within B:

    module B
      def method1
        "B\#method1"
      end
    
      def method2
        "B\#method2"
      end
    
      def self.append_features(mod)
        instance_methods(false).each { |method|
          mod.send(:remove_method, method) if mod.instance_methods(false).include?(method)
        }
        super
      end
    end