Re: redefining a method using Module#include
by Trans other posts by this author
Nov 12 2006 10:15AM messages near this date
Re: redefining a method using Module#include
|
RubyGems Issue
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]
There are a number of ways. To be clear you are asking for code inject
rather then inheritance. traditionally subclasses are used add
functionality, But with Ruby we have the power to directly effect core
classes. In doing so first ask yourself if you really need a module. If
not the simple do:
class Array
def if_absent_call(p)
...
alias :old_accessor :[]
def [](index)
...
The next levelup gets more complicated one way is to use the #included
callback to inject the code directly, but this is a misrepresentation
of what include should do (i.e. inheritance) and I strong discourage
it. Another related approach is alias_method_chain supported by both
ActiveSupport and Facets. Here is an example:
module X
def self.included(base)
base.module_eval {
alias_method_chain :foo, :feature
}
end
def foo_with_feature
foo_without_feature + '!'
end
end
class Y
def foo ; "FOO" ; end
include X
end
y = Y.new
assert_equal( "FOO!", y.foo )
But this would be a little tricker with an operator and it also has
it's own downsides. Other solution you can look into are Facets'
Module#prepend and Facets' Cut implementation.
Having said all that, you know what you are attempting to do is
dangerous stuff. Muckng with Array#[] may have sever side effects. In
this case, I highly recommend using singleton instead:
a = []
a.extend AbsenceHandling
Just replace #old_accessor with #super. It's a case be case basis, but
it's much safer and hek, it's easy :-)
T.
Thread:
Jan Svitok
Trans
|