ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> ruby-talk
ruby-talk
Re: redefining a method using Module#include
by Jan Svitok other posts by this author
Nov 12 2006 9:37AM messages near this date
Re: Where is attr_accessor located? | Re: redefining a method using Module#include
On 11/12/06, me@[...].net <me@[...].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 []
Thread:
Jan Svitok
Trans

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved