From: "T. Onoma" Date: 2003-12-07T00:16:58+09:00 Subject: mixins and extend (was: Attempted roadmap of future instance variables....) Can anyone take a look at this and tell me what the hek is happening with extend? (as in Pickaxe Chapter 19) ruby-talk:87344 I thought I finally understood, but now I'm just confused again. Thanks, T. Copy of 87344 follows: On Friday 05 December 2003 08:26 pm, T. Onoma wrote: > On Friday 05 December 2003 07:02 pm, Austin Ziegler wrote: > > It is a mix-in. > > > > class A; end > > class B; include Transaction::Simple; end > > x = A.new > > y = B.new > > x.extend(Transaction::Simple) > > class << x; self; end.ancestors > > => [Transaction::Simple, A, Object, Kernel] > > class << y; self; end.ancestors > > => [B, Transaction::Simple, Object, Kernel] > > > > It's just that #extend mixes into the object's singleton class. > > Hmm... Well, you actually prove my point. Transaction::Simple is coming > before A in the first case, and after B in the second. Quite different form > the ordinary mixin-in. Yet you'll have to excuse my while I scream > "Arrrrgggghhh!!!" b/c it is even more complex than I realized. So, yes, it > is techinaclly a mix-in per se, but since it is a mix-in on the sinlgeton > and not the class itself, it is more akin to a singleton. Or at least one > would think! But it seems it is actually more akin to just > redefining/restating the class: > > module M > def happy; print "M"; super if defined?(super); end > end > > class MC > def happy; print "M"; super if defined?(super); end > end > > class S < MC > def happy; print "x"; super if defined?(super); end > end > > class I > include M > def happy; print "x"; super if defined?(super); end > end > > class E > def happy; print "x"; super if defined?(super); end > end > > class C > def happy; print "x"; super if defined?(super); end > end > > s = S.new > > a = I.new > > b = E.new > b.extend(M) > > c = C.new > def c.happy; print "M"; super if defined?(super); end > > print "superclass: "; s.happy > print "\t", class << s; self; end.ancestors.inspect; puts > > print " include: "; a.happy > print "\t", class << a; self; end.ancestors.inspect; puts > > print " extend: "; b.happy > print "\t", class << b; self; end.ancestors.inspect; puts > > print " singleton: "; c.happy > print "\t", class << c; self; end.ancestors.inspect; puts > > This produces: > > superclass: xM [S, MC, Object, Kernel] > include: xM [I, M, Object, Kernel] > extend: M [M, E, Object, Kernel] > singleton: Mx [C, Object, Kernel] > > Notice in the singleton that "M" is invisible, but it does in fact exist > anonymously before C. > > I have to say, I'm actually very disturbed to see the x missing in the > extend. Where the heck did it go? Extending just redefined the happy method > altogether! That's not something I would call "extend". > > T.