Hi --

This has gotten bizarrely long.  But I think it's OK as an
explanation.

Finger crossed, candles lit, gods appeased... here I go.


On Fri, 16 Aug 2002, Hal E. Fulton wrote:

> ----- Original Message -----
> From: "ts" <decoux / moulon.inra.fr>
> To: "ruby-talk ML" <ruby-talk / ruby-lang.org>
> Cc: <ruby-talk / ruby-lang.org>
> Sent: Thursday, August 15, 2002 11:57 AM
> Subject: Re: Thought question: Where does "new" come from?
>
>
> > >>>>> "H" == Hal E Fulton <hal9000 / hypermetrics.com> writes:
> >
> > H> Why does the diagram show these parenthesized names?
> > H> I thought that Class was the only true metaclass in
> > H> Ruby. Why then do we show things like (Class) and
> > H> (Object) in the diagram?
> >
> >  (Class)  is the singleton class associated with Class
> >  (Object) is the singleton class associated with Object
>
> Oh, yes, of course. Where the singleton information
> goes.
>
> I am still unclear why these are conceptually
> necessary.
>
> If I do a "def Object.foo" why does it have to go into
> (Object) as opposed to just Object?

(See Mauricio's post also.)

If you have:

  class Thing
    def talk
      puts "hi"
    end
  end

  t = Thing.new

you've created a situation where t responds to 'talk'.  The basic
principle here is: for obj to respond to meth, meth has to be defined
as an instance method in obj's class.  (Or included module-wise, but
nevermind that.)

Now, let's say we'd done this instead (starting again here, not
cumulative):

  class Thing
  end

  t = Thing.new

Now, if we do this:

  def t.talk
    puts "hi"
  end
  t.talk

we've created another situation where t responds to talk.  And we know
from the principle stated above that for t to respond to talk, talk
has to be defined as an instance method in t's class.

Which means that by doing "def t.talk", we've just induced a new
instance method in t's class.

So now the question is, what is "t's class"?  We don't really want
"def t.talk" to retroactively make it as if we'd done

  class Thing
    def talk

since that would have all sorts of effect on all sorts of Things.  And
yet...  we *do* want it to be as if we'd been able to do:

  Hi, I'm in t's class, defining instance methods
    def talk

This is where the singleton class comes in.  It is, by definition,
that-which-is-the-class-of-t-and-only-t.  And it serves the purpose
being the class into which we can insert a new method for t, without
having to insert it into Thing.

I have found it helpful to think of the singleton class as being like
a very thin sheet of clear plastic, adhering to the underside of the
object's (non-singleton) class.  Sort of like a stick-on fake tatoo.
From the object's perspective, looking upward, anything written on the
plastic appears to be written directly on the "official" class.  From
the side (for example, when you do "obj.type" or "obj.is_a?"), the
plastic is so thin as to be invisible.  All you see is the object and
its non-singleton class.  And that class doesn't know the plastic is
there either.

Finally....

When you do

  def Object.foo

you're doing the same thing: you're defining a singleton method on the
object Object, and that method's home is as an instance method in
Object's singleton class.  "Object" here is filling exactly the same
role as "t" in the previous example.

Going back to your question:

> If I do a "def Object.foo" why does it have to go into
> (Object) as opposed to just Object?

If a method goes into Object, then it becomes a method of things that
are of type Object (or descendants):

  class Object
    def meth
  ...

  o = Object.new
  o.meth

What you want, however, is for foo to be a method of things that are
of type "the-thing-that-Object-is-a-type-of".  You could of course do
this on a non-singleton basis, since you know that Object is of type
Class:

  class Class
    def foo
    ...

  Object.foo

but what the "def obj.meth" syntax does is, as in the 't' example,
define the method as an instance method of the singleton class of the
object (which is Object, in this case).

Post-finally:  this is all also why you can do this:

  class << t
    def talk

It's another way of accomplishing the "Put me in t's singleton
superclass so I can define an instance method in it" thing.


David

-- 
David Alan Black
home: dblack / candle.superlink.net
work: blackdav / shu.edu
Web:  http://pirate.shu.edu/~blackdav