How to override static class method using module in Ruby?

前端 未结 3 872
再見小時候
再見小時候 2021-02-02 16:11
module Imodule
  ???
end

class Some
  include Imodule

  def self.imethod
    puts \"original\"
  end
end

Some.imethod
# => \"overrided\"

How to c

3条回答
  •  闹比i
    闹比i (楼主)
    2021-02-02 16:22

    What if you need to be able to call the original method that you just overrode, from within your new method?

    In other words, what if you want to be able to call super from an overridden class method the same way you might call super when overriding an instance method?

    Here's the solution I finally arrived upon, in case anyone else finds it useful:

    class Klass
      def self.say
        puts 'original, '
      end
    end
    
    module FooModule
      def self.included base
        orig_method = base.method(:say)
        base.define_singleton_method :say do |*args|
          orig_method.call(*args)
          puts "module"
        end
      end
    end
    
    
    class Klass
      include FooModule
    end
    
    Klass.say  # => original, module
    

    We have to use define_method instead of def so that we create a closure and have access to local variables (in this case, the saved version of the original method) from within the new method definition.

    By the way,

    base.define_singleton_method :say do
    

    is equivalent to doing

    (class << base; self; end).send :define_method, :say do
    

    .

    Special thanks to Ruby singleton methods with (class_eval, define_method) vs (instance_eval, define_method) and http://yugui.jp/articles/846 for educating me and pointing me in the right direction.

提交回复
热议问题