みんなのちからになりたい

コピペでブログラムつくっていきたい

moduleのメソッドでclassのメソッドをoverrideする

moduleのメソッドでclassのメソッドをoverrideしようとしてもならなかった。

module HogeHoge
  def hoge
    "hogehoge"
  end
end

class Hoge
  include HogeHoge
  def hoge
    "hoge"
  end
end

p Hoge.new.hoge


$ ruby test.rb
"hoge"

ならない。
ぐぐってみるとできないっぽい。
なんでできないのかという理由はいまいちわからなかったけど、この説明がなんとなくいちばん理解できた。

module - Ruby mixin override method clarification - Stack Overflow

So what you experience is normal. your Module M is a superclass of your class C
Therefore your foo method in class C overrides the foo method in module M

ならばsuperを入れてみる。

module HogeHoge
  def hoge
    "hogehoge"
  end
end

class Hoge
  include HogeHoge
  def hoge
    #"hoge"
    super
  end
end

p Hoge.new.hoge

$ ruby test.rb
"hogehoge"

なるほど。
じゃあどうするか。
alias_methodで別名つけてやったらできそうな気がするのでやってみる。

module HogeHoge
  def fugafuga
    "hogehoge"
  end
end

class Hoge
  include HogeHoge
  def hoge
    "hoge"
  end
  alias_method :hogehoge, :hoge
  alias_method :hoge, :fugafuga
end

p Hoge.new.hoge


$ ruby test2.rb
"hogehoge"

できた。
でもmoduleのメソッド名変えてるし、alias_methodを2回かまさないとダメなのですごいダサい気がする。
なんかないかなとぐぐってたらすごいいいやりかたしてるひとがいた。

overriding instance method with module - /dev/blog

initializeでextendする方法っぽい。
extendってVCとかでいうstaticだと思うんだけど、インスタンスメソッドより静的メソッドのほうが強いってことなのかな。
なによりインスタンス作ったときにそのobjectに静的メソッド生やすって考えがやばい気がする。
やってみる。

module HogeHoge
  def hoge
    "hogehoge"
  end
end

class Hoge
  def initialize
    extend HogeHoge
  end
  def hoge
    "hoge"
  end
end

p Hoge.new.hoge
test = Hoge.new
p test.hoge

$ ruby test3.rb
"hogehoge"
"hogehoge"

できた!
この発想すごい。


すごい勉強になる。