From: Rick DeNatale Date: 2010-08-02T01:48:35+09:00 Subject: Re: what is the correct way to extend native methods? On Sun, Aug 1, 2010 at 12:07 PM, Maurizio De Santis wrote: > Said that "is a bad idea to override a built-in method", I'm trying to > think in this way now: "what happens if I...", so I tried this: ... > instead, if I execute: > > module ExtendedSlicer >  def slice(*args) >    arg0 = args[0] >    case arg0 >      when Regexp >        grep(arg0) >      else >        super >    end >  end > end > > class Array >  include ExtendedSlicer > end > > arr = Array.new %w{a b c ab} > puts arr.slice(/a/).inspect # => can't convert Regexp into Integer > (TypeError) > > > Why? Maybe it is forbidden to include a Module in a built-in class, for > security reasons, or... boh! :) Can you explain that? It's because included modules are inserted after the class in the method lookup chain. They act more like a superclass in that regard, methods defined in a module don't override methods defined in classes which include the module. consider: module FooModule def foo "FooModule brand foo." end end class FooMaker def foo "FooMaker brand foo." end end class FooFighter < FooMaker include FooModule def foo "I'll do my own foo thank you." end end class FooInheritor < FooMaker end class FooIncluder include FooModule end class FooBothInheritAndInclude < FooMaker include FooModule end FooMaker.new.foo # => "FooMaker brand foo." FooFighter.new.foo # => "I'll do my own foo thank you." FooInheritor.new.foo # => "FooMaker brand foo." FooBothInheritAndInclude.new.foo # => "FooModule brand foo." # The ancestors method shows the order in which classes and modules are searched for a method: FooMaker.ancestors # => [FooMaker, Object, Kernel] FooFighter.ancestors # => [FooFighter, FooModule, FooMaker, Object, Kernel] FooInheritor.ancestors # => [FooInheritor, FooMaker, Object, Kernel] FooBothInheritAndInclude.ancestors # => [FooBothInheritAndInclude, FooModule, FooMaker, Object, Kernel] # Note that in the last case the leaf class doesn't define foo, and the method in FooModule overrides the one in FooMaker # And of course singleton methods trump everything: monty = FooBothInheritAndInclude.new monty.foo # => "FooModule brand foo." def monty.foo "and now for something completely different" end monty.foo # => "and now for something completely different" -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Github: http://github.com/rubyredrick Twitter: @RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale