do I really not understand inheritance?? 
Author Message
 do I really not understand inheritance??

So, I've been really trying to get a firm understanding of objects and
classes in Ruby.  Just to make sure I understood what was what, though, I
wrote a program to test my understanding.

As I understand it, asking:

  obj.kind_of? mod

..is the same as asking:

  obj.class.ancestors.include? mod

So I tested every object-class pair which comes standard with Ruby.  It
failed on two of these pairs, both with the Enumerable module.  Here's the
fast version of the code, working only with Enumerable:

  def doIGetIt? (obj)
    (obj.kind_of?(Enumerable)) == (obj.class.ancestors.include?(Enumerable))
  end

  ObjectSpace.each_object do |obj1|
    if !doIGetIt? obj1
      puts obj1.kind_of?(Enumerable)
      puts obj1.class.ancestors.inspect
      puts obj1
      puts obj1.class
      puts obj1.inspect
      puts
    end
  end

So, I'm assuming that it fails for you, too.  What's the deal with the ENV
object?  And what is that other '-' object?

Chris



Mon, 30 May 2005 04:50:14 GMT  
 do I really not understand inheritance??
Hi --

Quote:

> So, I've been really trying to get a firm understanding of objects and
> classes in Ruby.  Just to make sure I understood what was what, though, I
> wrote a program to test my understanding.

> As I understand it, asking:

>   obj.kind_of? mod

> ...is the same as asking:

>   obj.class.ancestors.include? mod

Not necessarily.  You can extend an object with a module individually:

  irb(main):001:0> a = Object.new
  #<Object:0x401df42c>
  irb(main):002:0> a.extend(Enumerable)
  #<Object:0x401df42c>
  irb(main):003:0> a.kind_of?(Enumerable)
  true
  irb(main):004:0> a.class.ancestors.include?(Enumerable)
  false

Here, I've extended the object to include Enumerable, but
only that one object.  Extending a means including Enumerable
in a's singleton class, which isn't the same as a.class.

And, sure enough:

  irb(main):008:0> class << a
  irb(main):009:1> puts "Yes" if self.ancestors.include?(Enumerable)
  irb(main):010:1> end
  Yes

Quote:
> [...]
> So, I'm assuming that it fails for you, too.  What's the deal with the ENV
> object?  And what is that other '-' object?

The object behind ENV does the above: it is an Object object which is
extended with Enumerable.  From hash.c:

  envtbl = rb_obj_alloc(rb_cObject);
  rb_extend_object(envtbl, rb_mEnumerable);
  ...
  rb_define_global_const("ENV", envtbl);

David

--
David Alan Black


Web:  http://pirate.shu.edu/~blackdav



Mon, 30 May 2005 05:39:40 GMT  
 do I really not understand inheritance??
AHA!!!

Thank you!

That damn hidden singleton class again...

So is there a way to get your real ancestors without jumping into (and thus
creating, if it didn't already exist) the singleton class using the
following trick?

  class << obj
    ...
  end

I don't understand why these singleton classes are "hidden" from us, when
they clearly make a difference from the coding side of things.  And they
aren't even hidden, since we can get references to them if we want to (but
again, only by creating them if they didn't exist):

  klass = class << obj; self; end

How am I supposed to get all of the Classes/Modules which some object 'obj'
is a kind_of?  Get klass (as above) and call klass.ancestors?

I guess all of my confusion, and thus my ultimate complaint comes back to
this:

Why doesn't the 'class' method return the singleton class?

Moreover, check this out:

  class Foo
  end

  foo = Foo.new

  klass = class << foo; self; end

  p foo.instance_of? Foo    #  -->  true
  p foo.instance_of? klass  #  -->  false

That doesn't seem right to me at all.  (Though it does seem consistent, just
consistently wrong... or at least confusing.)  I would say that foo *was* an
instance of Foo, but that changed when you made foo do things other Foo's
couldn't.  At that point (when foo got it's own singleton class), foo became
an instance of klass.

Why do we make singleton classes special at all?  What I mean is, why make
them singletons??  (I'm sure there's a good reason... I just want to know
what it is.)  If I say:

  class Foo
  end

  foo = Foo.new

  def foo.bar
    'bar'
  end

..why not just have the new regular (non-singleton) class created?  Is it
such a terrible thing that someone *might* try to instantiate the class??
It seems to be that Ruby would be just that much simpler to understand (and
maybe even to implement).

What would we lose by switching singleton classes to regular classes?

Chris



Mon, 30 May 2005 08:54:40 GMT  
 do I really not understand inheritance??
Hi --

Quote:

> How am I supposed to get all of the Classes/Modules which some object 'obj'
> is a kind_of?  Get klass (as above) and call klass.ancestors?

To get all of them you'd want to traverse both the singleton class and
the non-singleton [do we have a better word than that?] class:

  class Object
    # This doesn't save any typing in this example, but
    # it can come in handy in the long run :-)
    def singleton_class
      class << self; self; end
    end

    def all_ancestors
      (singleton_class.ancestors + self.class.ancestors).uniq
    end
  end

  p ENV.all_ancestors   # [Enumerable, Object, Kernel]

Quote:
> I guess all of my confusion, and thus my ultimate complaint comes back to
> this:

> Why doesn't the 'class' method return the singleton class?

Consider this:

  class A
    def A.some_method
      "hi"
    end
  end

I've defined a singleton method on the object A, which is a Class
object.  This singleton method is defined (by definition) in A's
singleton class.

Now, according to what you're suggesting, A would no longer be a Class
object, but would be a "class << A; self; end" object.  Then let's say
we do this:

  a = A.new

Well, A is not a Class any more, but let's assume it still responds to
'new'....  But what do we get from this:

  a.class

We can't get A, because A is no longer a Class!  So by simply adding a
singleton method to an object, we've tied everything in knots.

This example uses the familiar scenario of class methods (i.e.,
singleton methods added to Class objects), but the lesson is general:
the notion of the singleton class is part of a whole design, and can't
just be changed or discarded.  (I also happen to think it's intensely
cool, but I won't push that at the moment :-)

Quote:
> Moreover, check this out:

>   class Foo
>   end

>   foo = Foo.new

>   klass = class << foo; self; end

>   p foo.instance_of? Foo    #  -->  true
>   p foo.instance_of? klass  #  -->  false

> That doesn't seem right to me at all.  (Though it does seem consistent, just
> consistently wrong... or at least confusing.)  I would say that foo *was* an
> instance of Foo, but that changed when you made foo do things other Foo's
> couldn't.  At that point (when foo got it's own singleton class), foo became
> an instance of klass.

I think you have to look at the overall design of Ruby, which
incorporates these two distinct constructs which have distinct roles.
They're not at war.  An object has a historical class, which is what
it was instantiated as, and it has a private "stash" of individuated
behavior which is called its singleton class.  Neither of these
obliterates the other.

Mind you, I don't want to discourage the loosening of the notion of an
object's "class".  Imagine what would happen to the idea of testing
for type:

  case thing
  when String ...
  when Array  ...
  when Thingy ...

if adding a singleton method to thing changed its class!

However, one thing at a time :-)  The design really does make sense.

Quote:
> [...]
> ...why not just have the new regular (non-singleton) class created?  Is it
> such a terrible thing that someone *might* try to instantiate the class??

I'm tempted to say: think of it as a pseudo-class, or something,
though I don't want to muddy the waters of terminology.  In practical
terms, one thing to keep in mind is that nothing is denied you.  Ruby
offers a full suite of techniques for manipulating objects and their
capabilities.  The key to this is modules: mixing and matching object
capabilities through modules, objects can share exactly the kinds of
relations that one envisions with the (paradoxical) "multiple objects
of a singleton class" concept.

David

--
David Alan Black


Web:  http://pirate.shu.edu/~blackdav



Mon, 30 May 2005 12:32:43 GMT  
 do I really not understand inheritance??
Hmm....  I see what you're saying, I think.  I was going to give you a
counter-example, but I can't because you can't subclass Class.  This, of
course, begs the question:  Why can't you subclass Class?

Here's why I ask:

Let's say you have a class 'A', and an instance 'a' of 'A'.  So, at this
point, a's klass pointer points to A, A's klass pointer points to Class, and
A's super pointer points to Object.  (For my diagrams, let's say klass
pointers are vertical and super pointers are horizontal.)

            Class
              ^
              |
              |
Object  <---  A
              ^
              |
              |
              a

I'm saying that I think a singleton class of a (which I will call A:a,
because it sort of sits between A and a, and because it is sort of the "new
A" for a) should be a regular class which subclasses A, like this:

               Class
              ^      ^
              |      |
              |      |
Object  <---  A <-- A:a
                     ^
                     |
                     |
                     a

(The klass pointers of A and A:a are pointing at Class; they are both
classes.)  So what are the ramifications of this idea for classes?  More
specifically, what happens if I define a class method of A, creating a
singleton class (which I will call Class:A)?  Well, it seems like it should
work like this:

Class   <---  Class:A
              ^      ^
              |      |
              |      |
Object  <---  A <-- A:a
                     ^
                     |
                     |
                     a

(Now the klass pointers of A and A:a are pointing to Class:A.  Also, I
assumed that we made Class:A *before* A:a, but that's almost always the
case; most classes have singleton classes already, if only to handle the
method 'new'.)  Currently, this is impossible, though, because you can't
subclass Class; my idea of Class:A is that it is a subclass of Class.

To me, this all seems much more natural.  We didn't create any sort of
bizarre "hidden" class (and no matter how cool you may find the
functionality currently provided by singleton classes, they themselves are
totally exceptional and bizarre) to make everything work.

So what am I missing?  Why can't you subclass Class?  Was this for the sake
of implementation?  I can't imagine it's just so we can have singleton
classes.  (That would be like having your tooth drilled just so you can have
a filling... if there's no cavity (implementation problem), couldn't we just
skip the whole thing?)

Quote:
----- Original Message -----

[snip]

Mind you, I don't want to discourage the loosening of the notion of an
object's "class".  Imagine what would happen to the idea of testing
for type:

  case thing
  when String ...
  when Array  ...
  when Thingy ...

if adding a singleton method to thing changed its class!
----------------------------

Well, I thought it was understood that testing for type is a Bad Thing.  If
anything, one should test for kind_of?, which is actually what Module#===
does anyway (which is a Good Thing).  So the above code would work just
fine.  Adding a singleton method might change an object's class, but it
would still be a kind_of? its original class.

----------------------------
To get all of them you'd want to traverse both the singleton class and
the non-singleton [do we have a better word than that?] class:

  class Object
    # This doesn't save any typing in this example, but
    # it can come in handy in the long run :-)
    def singleton_class
      class << self; self; end
    end

    def all_ancestors
      (singleton_class.ancestors + self.class.ancestors).uniq
    end
  end

  p ENV.all_ancestors   # [Enumerable, Object, Kernel]

----------------------------

Are you sure?  I don't think you need to even look at self.class.ancestors;
everything you need is in singleton_class.ancestors (suggesting what I am
advocating above... it really seems like Ruby only went half-way with this
one).  In any case, regarding the above, I was asking if there was a way to
get the singleton class *without* creating one in the process (as you have
done), in which you get the singleton class if it already exists, or nil if
it doesn't.  But, it probably isn't possible.

Thank you MUCH for your very thoughtful and thought-provoking response!

Chris



Mon, 30 May 2005 14:57:34 GMT  
 do I really not understand inheritance??
I don't understand all of this discussion, but the following may be
helpful.

 From "The Ruby Way":

"Ruby classes are themselves objects, being instances of the metaclass
Class. . . . The class Object is at the root of the hierarchy. . . .
Object itself is the only object without a superclass."

As I understand it, Class cannot be subclassed because it is an object
(a kind of metaclass).

[You have to start somewhere . . .].

Singleton classes are a direct implementation of the singleton design
pattern.  (see http://www.rubygarden.org/ruby?SingletonPattern).

Ruby's class hierarchy chart is in a comment in the object.c file of
the source.  The chart notes that all metaclasses are instances of the
class 'Class'.

But here, matz says there are no metaclasses in Ruby:
http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/40537.

But after a question about meta-objects and singleton methods
(http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/40545) yields
the following response from matz:
http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/40548.

Smalltalk's use of metaclasses, and the problem being addressed, is
explained in semi-understandable language here:
http://wiki.cs.uiuc.edu/VisualWorks/How+do+metaclasses+work%3F

Quote:

> Hmm....  I see what you're saying, I think.  I was going to give you a
> counter-example, but I can't because you can't subclass Class.  This,
> of
> course, begs the question:  Why can't you subclass Class?

> [snip]
> To me, this all seems much more natural.  We didn't create any sort of
> bizarre "hidden" class (and no matter how cool you may find the
> functionality currently provided by singleton classes, they themselves
> are
> totally exceptional and bizarre) to make everything work.

> So what am I missing?  Why can't you subclass Class?  Was this for the
> sake
> of implementation?  I can't imagine it's just so we can have singleton
> classes.
> [snip]



Mon, 30 May 2005 16:58:57 GMT  
 do I really not understand inheritance??
Here are the links in my prior message without adjacent punctuation:

http://www.rubygarden.org/ruby?SingletonPattern

http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/40537

http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/40545

http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/40548

http://wiki.cs.uiuc.edu/VisualWorks/How+do+metaclasses+work%3F



Mon, 30 May 2005 17:07:29 GMT  
 do I really not understand inheritance??

Quote:
> Here are the links in my prior message without adjacent punctuation:
> [...]
> http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/40537
> [...]

Mark,

Do you know that the above link is equivalent to
   http://www.ruby-talk.org/40537
?

Anyway, I've saved your previous message at
  http://www.rubygarden.org/ruby?GavinSinclair/MetaClassDiscussion

Gavin



Mon, 30 May 2005 17:22:22 GMT  
 do I really not understand inheritance??
Hi --

Quote:

> Hmm....  I see what you're saying, I think.  I was going to give you a
> counter-example, but I can't because you can't subclass Class.  This, of
> course, begs the question:  Why can't you subclass Class?

I'm now researching that question :-)  From the previous discussions
I've found, which include some posts I'm still puzzling through, the
basic answer seems to be: if you subclass Class, then you propagate
the weird circularity at the top of the tree down into the whole
tree.  That weird circularity being the thing where Object is a Class,
but Class is an object, and Class inherits from Module, but Module is
a Class....  Luckily Ruby takes care of all of this at that level, and
the idea is not to recapitulate it later down the line in other
cases.

Quote:

> [snip]

> Mind you, I don't want to discourage the loosening of the notion of an
> object's "class".  Imagine what would happen to the idea of testing
> for type:

>   case thing
>   when String ...
>   when Array  ...
>   when Thingy ...

> if adding a singleton method to thing changed its class!
> ----------------------------

> Well, I thought it was understood that testing for type is a Bad Thing.  If

Yes, I certainly tend to look at it that way.  My point was that
changing an object's class might have the positive effect of making
such tests so meaningless so often that people would stop doing them
:-)  By the way, there have been discussions of the idea of having a
'become' method in Ruby, which you might find interesting.

Quote:
>> To get all of them you'd want to traverse both the singleton class and
>> the non-singleton [do we have a better word than that?] class:
> Are you sure?  I don't think you need to even look at self.class.ancestors;

Whoops, you're right.

Quote:
> everything you need is in singleton_class.ancestors (suggesting what
> I am advocating above... it really seems like Ruby only went
> half-way with this one).  In any case, regarding the above, I was
> asking if there was a way to get the singleton class *without*
> creating one in the process (as you have done), in which you get the
> singleton class if it already exists, or nil if it doesn't.  But, it
> probably isn't possible.

I don't know how you'd do that, but I don't think it's very expensive
or significant to create the singleton class.

David

--
David Alan Black


Web:  http://pirate.shu.edu/~blackdav



Mon, 30 May 2005 20:51:19 GMT  
 do I really not understand inheritance??

d> I'm now researching that question :-)

 Just an example (it's 1.7)

pigeon% cat b.rb
#!./ruby
class A < Class
   def self.a
      p "a"
   end

   def a
      p "a"
   end
end

b = A.new
b.a
pigeon%

pigeon% b.rb
/b.rb:13: undefined method `a' for #<Class:0x401ac244> (NoMethodError)
pigeon%

Guy Decoux



Mon, 30 May 2005 21:05:10 GMT  
 do I really not understand inheritance??
Quote:
> I don't understand why these singleton classes are "hidden" from us, when
> they clearly make a difference from the coding side of things.  And they
> aren't even hidden, since we can get references to them if we want to (but
> again, only by creating them if they didn't exist):

[...]

Hi. FWIW, my understanding is that the design idea is not to play with
metaclasses but to extend objects' behavior; and that singleton classes are
only an artifact to do this.



Mon, 30 May 2005 21:33:15 GMT  
 do I really not understand inheritance??
Now that's interesting...

When I ask, "Why *can't* we subclass Class?" it's because I *can't*... but
you did!  For me, when it gives:

  can't make subclass of Class (TypeError)

This is ruby 1.7.3 (2002-11-17) [i386-mswin32].

What I was trying to do was make a new Class, called NewClass, which would
work like this:

  NewClass = Class.new Class

  A = Class.new     #  Creates a class.
  B = NewClass.new  #  Creates a class (I was hoping).

  A.kind_of? Class  #  -->  true
  B.kind_of? Class  #  -->  true

  a = A.new
  b = B.new

Seems to me that any object which defines a 'new' method should be
considered a class... isn't this one of the major ideas behind dynamic
typing?

I understand that if you use the following language construct:

  class Foo
  end

..this is the same as 'Foo = Class.new', and that there is no corresponding
language construct for creating classes of any other klass (their klass
pointers currently ALWAYS point to Class), but why isn't it allowed?

Quote:
----- Original Message -----

Just an example (it's 1.7)

pigeon% cat b.rb
#!./ruby
class A < Class
   def self.a
      p "a"
   end

   def a
      p "a"
   end
end

b = A.new
b.a
pigeon%

pigeon% b.rb
/b.rb:13: undefined method `a' for #<Class:0x401ac244> (NoMethodError)
pigeon%

----------------------------

This makes perfect sense.  A is a class-making class (like Class is).  It
inherits Class's new method, which creates a new instance of Class, not of
A.  *This* is what I was trying to show (but I can't subclass classes, so
thank you!).

This just tells me that Class.new is broken.  It should return an object
whose klass pointer is *self*, not Class.  Then the above code would work,
and we could get rid of singleton classes altogether, in favor of simply
inserting real classes into the hierarchy.  This would also encourage people
to use #kind_of? instead of #class, which is a Good Thing.

We would still have all of the functionality singleton classes now provide,
but no 'special hidden singleton' classes, which even matz says are not part
of the Ruby language (only this implementation of it).

Ruby 2.0 anyone?  :)

Seriously, I'm no language designer, so if there are other problems with
subclassing Class (in principle, not in the current implementation), please
tell me what they are.

Chris



Mon, 30 May 2005 23:39:27 GMT  
 do I really not understand inheritance??
Using irb in 1.6.7, an attempt to subclass Class gives:

TypeError: can't make subclass of Class
         from (irb):3:in `inherited'
         from (irb):3

The same error is given using a program.

1.  Is the difference between 1.6 and 1.7 intentional?

2.  If you can't define a method for an attempted subclass of Class,
have you actually created a subclass of Class in 1.7?

Quote:


> d> I'm now researching that question :-)

>  Just an example (it's 1.7)

> pigeon% cat b.rb
> #!./ruby
> class A < Class
>    def self.a
>       p "a"
>    end

>    def a
>       p "a"
>    end
> end

> b = A.new
> b.a
> pigeon%

> pigeon% b.rb
> ./b.rb:13: undefined method `a' for #<Class:0x401ac244> (NoMethodError)
> pigeon%

> Guy Decoux



Tue, 31 May 2005 00:16:28 GMT  
 do I really not understand inheritance??
Hi --

Quote:

> Now that's interesting...

> When I ask, "Why *can't* we subclass Class?" it's because I *can't*... but
> you did!  For me, when it gives:

Guy has his own versions of Ruby, and doesn't always explicitly tell
us he's using them.  (Guy, do you have a "-w" flag? :-)

It's an easy hack, though, if you want to try it.  In 1.7, look in
class.c for rb_class_new, and comment out the tests.  (I think it was
in object.c earlier.)

Quote:
> ----- Original Message -----
> Just an example (it's 1.7)

> pigeon% cat b.rb
> #!./ruby
> class A < Class
>    def self.a
>       p "a"
>    end

>    def a
>       p "a"
>    end
> end

> b = A.new
> b.a
> pigeon%

> pigeon% b.rb
> /b.rb:13: undefined method `a' for #<Class:0x401ac244> (NoMethodError)
> pigeon%

> ----------------------------

> This makes perfect sense.  A is a class-making class (like Class is).  It
> inherits Class's new method, which creates a new instance of Class, not of
> A.  *This* is what I was trying to show (but I can't subclass classes, so
> thank you!).

> This just tells me that Class.new is broken.  It should return an object
> whose klass pointer is *self*, not Class.  Then the above code would work,
> and we could get rid of singleton classes altogether, in favor of simply
> inserting real classes into the hierarchy.  This would also encourage people
> to use #kind_of? instead of #class, which is a Good Thing.

They're both forms of testing for type, which I'm not a big fan of
personally.  I'd rather see the role of class hierarchies diminish
than see it grow, and more be made of the behavior of objects at a
given point in their lifespan.

Quote:
> We would still have all of the functionality singleton classes now provide,
> but no 'special hidden singleton' classes, which even matz says are not part
> of the Ruby language (only this implementation of it).

If I understand matz's remarks correctly, this question of
implementation is not a question of semantics.  In other words, the
"singleton class notation" (class << obj) is a semantic feature of
Ruby.  How it's implemented (whether through the creation of a class
object, or otherwise) is another matter.

Although...  I'm actually not sure how different an implementation
could be, since presumably "class << obj; self; end" has to evaluate
to something.  I guess that's actually part of what matz considers
abusive use of that notation (http://www.ruby-talk.org/40548).

In any case, if there's a way to do singleton methods without
singleton classes, I guess that would be OK (though I actually cannot
picture how it would work).  But I don't think we'd then want to see
the ghosts of singleton classes becoming real classes.

David

--
David Alan Black


Web:  http://pirate.shu.edu/~blackdav



Tue, 31 May 2005 00:17:12 GMT  
 do I really not understand inheritance??

 Well, this must be read

Quote:
>> Just an example (it's 1.7)

                   (it's a private and modified version of 1.7)

Guy Decoux



Tue, 31 May 2005 00:19:54 GMT  
 
 [ 24 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Doing assembly and really doing assembly

2. Doing assembly and really doing assembly

3. I really don't understand Lambda!

4. Does Ada really need MULTIPLE inheritance?

5. WHAT ARE THE KIDS REALLY DOING ONLINE..

6. WHAT ARE EMPLOYEES REALLY DOING ONLINE^^^

7. PIL+Tkinter query (I must be doing something _really_ stupid)

8. - Unreliability - #referentAddress message not understood

9. Message not understood: #printOn:depth

10. Kernel does not understand "abtPackagerOpenInitialViews"

11. VWNC: aString asInteger - does not understand?

12. Mainframe-PC data conversion not understood

 

 
Powered by phpBB® Forum Software