From: Maurizio De Santis on 1 Aug 2010 12:07 David A. Black wrote: > > module ExtendedSlicer > def slice(*args) > arg0 = args[0] > case arg0 > when Regexp > grep(arg0) > else > super > end > end > end > > a = %w{ one two three four }.extend(ExtendedSlicer) > a.slice(0,2) # ["one", "two"] > a.slice(/o/) # ["one", "two", "four"] > > The main advantage here is that it's a better fit: you need an object to > behave a certain way, and you teach that object to behave that way. > Another advantage is that it makes you work a little harder, and > therefore helps you evaluate more carefully whether or not you need to > perform the modification at all. > Ok, I've learned more from these posts than in two months of experiments. 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: class MyArray < Array; end module ExtendedSlicer def slice(*args) arg0 = args[0] case arg0 when Regexp grep(arg0) else super end end end class MyArray include ExtendedSlicer end arr = MyArray.new %w{a b c ab} puts arr.slice(/a/).inspect => it writes ["a", "ab"] ; correct 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? -- Posted via http://www.ruby-forum.com/.
From: Rick DeNatale on 1 Aug 2010 12:48 On Sun, Aug 1, 2010 at 12:07 PM, Maurizio De Santis <desantis.maurizio(a)gmail.com> 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
From: Jean-Julien Fleck on 1 Aug 2010 12:49 Hello, > Why? Maybe it is forbidden to include a Module in a built-in class, for > security reasons, or... boh! :) Can you explain that? I think it has to do with inheritance when looking for methods. First, ruby look in the class itself to see if there is a method named 'slice'. When you try to extend Array, it find Array's original 'slice' and so does not need to look at the module (and never find your redefinition). If no method of that name is found in the class (like MyArray), it looks in the modules (if any) included in your class (and find one 'slice' in ExtendedSlicer) before looking at the ancestor class (which is Array). If I'm not mistaken, it should explain the observed behavior. All that (and more ! :o) is explained in David's book (The Well-Grounded Rubyist) in a crystal-clear manner around p100 of my version. Cheers, -- JJ Fleck PCSI1 Lycée Kléber
From: Maurizio De Santis on 1 Aug 2010 15:55 Clear as spring wat - better do not mention Spring! - bright as a flawless Ruby! :D Thanks to everyone! And forgive me for the joke :P -- Posted via http://www.ruby-forum.com/.
First
|
Prev
|
Pages: 1 2 3 Prev: FREE SOFTWARE Next: Could I build a video chat site with ruby on rails? |