T
T. Onoma
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:
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:
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.