From: Jean-denis Vauguet on 21 Mar 2010 15:51 Robert Klemme wrote: > On 03/21/2010 06:14 PM, James Edward Gray II wrote: >>> Not really sure about it, but... >> >> It worked great and felt very natural to me when using it. > > James, what's the advantage of this over simply using "include"? If all > instances get to use the plugin module then you can as well include it > in the class. As JEGII stated, the main reason to do so is related to the inheritance chain order. If you want to be able to redefine an instance method while keeping access to the original implementation, extend is necessary. include will make the redefinition available but as it's mixed-in, the original definition trumps the redef. With extend, the order is reversed (the original class is kind of subclassed by the module extend receives as an argument). This is terrific behavior for callbacks and plugins. It's a easy as pie to do with classes, and a little bit more tortuous to achieve for class instances. > I see it like this: if all instances of a class should be extended with > plugin behavior, then simply use "include". If only some instances > should, then use "extend". I think there's some confusion about what extend and include really are. We often read extend is to make module methods available as class methods while include makes them instance methods, but that's not true. extend is a method of the Object class, and it can handle any object as a receiver, be it a class, an instance of a class, or a module, a singleton, etc. If you extend a class, then you'll get class methods. An instance, instance methods. And what's so great about extend is, once again, the way it alters the inheritance chain: the class calling extend for a module gets subclassed by the module-now-a-class. Which means at least two things: if you redefine the module passed to extend, then the changes are not propagated, it's made available only for new extending objects; if you had a method on the object which is redefined into the extended module, then the module-now-a-class version is the first match, and you can call super to reach the original (class) definition. Quite different is include, a keyword not a method, which has only one behavior: quoting the Pickaxe, "it makes a reference from the class to the included module. If multiple classes include that module, they'll all point to the same thing". So you get shared, instance methods. The mixed-in module is appended right next to the class including it within the inheritance chain, so that if you call an instance method of the class, even if it's been redefined by the mixed-in module, the first match's still the class'. So, the real difference between extend and include, aside from their nature, is not really about whether they're talking to classes or instances, it's more about their behavior: extend is useful for redefining things (once), include (mixin) is useful for adding (shared) things. I mean, following Yehuda Katz (http://yehudakatz.com/2010/02/25/rubys-implementation-does-not-define-its-semantics/), you can either stick to the implementation, or, you can consider the semantic/purpose, the latter being more accurate and useful at the same time IMO :) -- Posted via http://www.ruby-forum.com/.
From: James Edward Gray II on 21 Mar 2010 16:15 On Mar 21, 2010, at 2:51 PM, Jean-denis Vauguet wrote: > extend is a method of the Object class, and it can handle any object as > a receiver, be it a class, an instance of a class, or a module, a > singleton, etc. If you extend a class, then you'll get class methods. An > instance, instance methods. And what's so great about extend is, once > again, the way it alters the inheritance chain: the class calling extend > for a module gets subclassed by the module-now-a-class. > Quite different is include, a keyword not a method, which has only one > behavior: quoting the Pickaxe, "it makes a reference from the class to > the included module. If multiple classes include that module, they'll > all point to the same thing". So you get shared, instance methods. > So, the real difference between extend and include, aside from their > nature, is not really about whether they're talking to classes or > instances, it's more about their behavior: extend is useful for > redefining things (once), include (mixin) is useful for adding (shared) > things. This isn't totally accurate. extend() is a stupid simple shortcut that really is just an include. This code: obj.extend(Whatever) is identical to: class << obj include Whatever end So it really does all work the same. The reason it moves the methods in front of the main class though is that the singleton class is in front of the main class. Thus including the module behind that class still has them in front of the main class. I talked about this quite a bit in my presentation at LSRC last year: Video: http://lsrc2009.confreaks.com/module-magic-james-edward-gray-ii-28-aug-2009.html Slides: http://grayproductions.net/ruby/module_magic.tar.gz The spirit of what you said is all right on though. James Edward Gray II
From: Jean-denis Vauguet on 21 Mar 2010 16:21 James Edward Gray II wrote: > http://github.com/JEG2/prawn/commit/7e25bafe16f508a080a41979bfe25b47f97f0a5e > > I hope that helps. Thank you, this is art. I'm happy to see I did it roughly the same way, minus the (very smart) tests :) -- Posted via http://www.ruby-forum.com/.
From: Jean-denis Vauguet on 21 Mar 2010 16:25 James Edward Gray II wrote: > On Mar 21, 2010, at 2:51 PM, Jean-denis Vauguet wrote: >> stuff. > This isn't totally accurate. extend() is a stupid simple shortcut that > really is just an include. This code: > > obj.extend(Whatever) > > is identical to: > > class << obj > include Whatever > end > > So it really does all work the same. That's even better than expected! I did not think about the singleton class nor did I look at the real implementations (which demonstrates it *is* important to master along the semantics ;)). Thanks for the correction. > The reason it moves the methods in front of the main class though is > that the singleton class is in front of the main class. Thus including > the module behind that class still has them in front of the main class. > > I talked about this quite a bit in my presentation at LSRC last year: > > Video: > http://lsrc2009.confreaks.com/module-magic-james-edward-gray-ii-28-aug-2009.html > Slides: http://grayproductions.net/ruby/module_magic.tar.gz > > The spirit of what you said is all right on though. -- Posted via http://www.ruby-forum.com/.
From: Jean-denis Vauguet on 22 Mar 2010 04:04 I just finished writing my plugins system. It's working like a charm, thank you for your feedbacks! I may extract a standalone gem which would allow any module (or class, but typically it's to be called on a project module) to enable plugins and project internals redefinition on the fly, without the need for any aliasing or explicit callback definition. I need to streamline my current code, though. -- Posted via http://www.ruby-forum.com/.
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 Prev: [ANN] Kanocc 0.2.0 Next: Ruby/Tk: How to colorize a Treeview? |