mixins and extend (was: Attempted roadmap of future instance variables....)

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:

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

ts

T> Can anyone take a look at this and tell me what the hek is happening with
T> extend? (as in Pickaxe Chapter 19)

Well, I've not understood your problem.

To simplify : by default (because it's possible to redefine what do ruby)
an extend can be seen as an include in the singleton class.

For your example
c = C.new
def c.happy; print "M"; super if defined?(super); end
[...]
singleton: Mx [C, Object, Kernel]

Notice in the singleton that "M" is invisible, but it does in fact exist
anonymously before C.

M is not invisible : it just don't exist. You have just defined a method
#happy for `c', like the module M define a method #happy


Guy Decoux
 
T

T. Onoma

T> Can anyone take a look at this and tell me what the hek is happening
with T> extend? (as in Pickaxe Chapter 19)

Well, I've not understood your problem.

Thanks for responding, Guy. I'll explain better.
To simplify : by default (because it's possible to redefine what do ruby)
an extend can be seen as an include in the singleton class.

"seen as an include in the singleton class": That's what confuses me. I can
"see" this by combing the diagrams on Pickaxe pg. 246 and 247, no problem.
But it dosen't explain to me why x isn't printed in my extend example.

(I wish there way a way I could draw a picture of it here)
singleton: Mx [C, Object, Kernel]

Notice in the singleton that "M" is invisible, but it does in fact exist
anonymously before C.

M is not invisible : it just don't exist. You have just defined a method
#happy for `c', like the module M define a method #happy

Indeed I have defined that method, but it is put in a an unnamed class, i.e.
the singleton class. (Pickaxe Figure 19.2 on page 246, has a diagram of it.)
I'm simply refering to it as M, analogous to the rest of the examples. This
is why M is printed before x and dosen't simply replace x.

T.

[NOTE: I figured it out and it may be a bug in Ruby. At the the very least it
is a "bugaboo". I'll explain in next message -T.]
 
T

T. Onoma

Take a look at this:

class MC
def happy; print "C"; super if defined?(super); end
end

module M
def happy; print "M"; super if defined?(super); end
end

class S < MC
include M
def happy; print "x"; super if defined?(super); end
end

s = S.new

print "superclass: "; s.happy
print "\t", class << s; self; end.ancestors.inspect; puts

Outputs:

superclass: xM [S, M, MC, Object, Kernel]

Now look at this:

class MC
def happy; print "C"; super if defined?(super); end
end

module M
def happy; print "M"; super; end
end

class S < MC
include M
def happy; print "x"; super if defined?(super); end
end

s = S.new

print "superclass: "; s.happy
print "\t", class << s; self; end.ancestors.inspect; puts

Outputs:

superclass: xMC [S, M, MC, Object, Kernel]

The last is what one would expect. Seems that defined?(super) dosen't work
with mixins even though calling super does. What do you make of that? Bug?

T.
 
T

ts

T> superclass: xM [S, M, MC, Object, Kernel]

svg% cat b.rb
#!./ruby -v
class MC
def happy; print "C"; super if defined?(super); end
end

module M
def happy; print "M"; super if defined?(super); end
end

class S < MC
include M
def happy; print "x"; super if defined?(super); end
end

s = S.new

print "superclass: "; s.happy
print "\t", class << s; self; end.ancestors.inspect; puts
svg%

svg% b.rb
ruby 1.8.1 (2003-11-30) [i686-linux]
superclass: xMC [S, M, MC, Object, Kernel]
svg%


Guy Decoux
 
T

T. Onoma

svg% b.rb
ruby 1.8.1 (2003-11-30) [i686-linux]
superclass: xMC [S, M, MC, Object, Kernel]
svg%

So what do you know:

ruby 1.8.0 (2003-08-04) [i686-linux]
superclass: xM [S, M, MC, Object, Kernel]

Cool, so it's been fixed! And I do understand correctly, and I have all along.
Guess it's time to upgrade.

Whew! That really scared the hek out of me. My world started to come tumbling
down. But super Guy was there to keep the sky from falling :)

Thanks, Guy.
T.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top