From: Jan Svitok Date: 2006-11-13T02:37:18+09:00 Subject: Re: redefining a method using Module#include On 11/12/06, me@mikehogan.net wrote: > Hi, > > How can I redefine Array#[] using an included Module? Here is my > attempt: > > module AbsenceHandling > def if_absent_call(p) > @if_absent = p > self > end > > def [](index) > result = old_accessor(index) > if(result.nil? && !@if_absent.nil?) > result = @if_absent.call(index) > self[index]=result > end > result > end > end > > class Array > alias :old_accessor :[] > include AbsenceHandling > end > > > x = [1,2,3].if_absent_call(proc{|index| > "#{index}" > }) > puts x[5] Hi, If a class defines a method, it has higher precedence than methods of any of its included modules. So the "override" never happens in this case. You can work around it by defining the [] operator directly in Array method, via Module#included and Module#define_method. You can alias the old [] in the included as well. module AbsenceHandling def if_absent_call(p) @if_absent = p self end def self.included(base) # base = Array in this case # alias_method and define_method are private, so we must # use the send trick base.send(:alias_method, :old_accessor, :[]) base.send(:define_method, :[]) do |index| result = old_accessor(index) if(result.nil? && !@if_absent.nil?) result = @if_absent.call(index) self[index]=result end result end end end class Array include AbsenceHandling end Note: [] in Array is a special case (as are some other methods in base C classes) as sometimes their C versions are called directly for the sake of speed. So e.g. Array#to_s will use the old []