Metaclasses

Discussion in 'Ruby' started by Neil Curzon, Nov 8, 2007.

  1. Neil Curzon

    Neil Curzon Guest

    Hi, all. I'm trying to understand chapter 24 of Programming Ruby.
    I'm using "metaid.rb" from why the lucky stiff's site to help with the
    examples. (http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html)

    Everything is pretty straightforward except for the diagrams of
    inheritance of metaclasses. Figure 24.2 indicates that for a direct
    subclass of Object, its metaclass's superclass should be Object's
    metaclass. When I try this out in irb, I don't get the expected
    result.

    $ irb -r metaid
    irb(main):001:0> String.metaclass
    => #<Class:String>
    irb(main):002:0> String.metaclass.superclass
    => #<Class:Class>
    irb(main):003:0> String.metaclass.superclass == Object.metaclass
    => false

    Surprisingly, when I try it in JRuby, I do get the expected result.

    $ jirb -r metaid
    irb(main):001:0> String.metaclass
    => #<Class:String>
    irb(main):002:0> String.metaclass.superclass
    => #<Class:Object>
    irb(main):003:0> String.metaclass.superclass == Object.metaclass
    => true

    Also, figure 24.3 suggests that for an instance of String, the
    metaclass should be a virtual class extending String itself.

    Once again only JRuby produces the expected result.

    $ irb -r metaid
    irb(main):001:0> String.new.metaclass.superclass == String
    => false

    $ jirb -r metaid
    irb(main):001:0> String.new.metaclass.superclass == String
    => true

    Something else I found weird is that when I go up the inheritance of a
    String instance's metaclass in plain ruby, I quickly run into a loop:

    $ irb -r metaid
    irb(main):001:0> c = String.new.metaclass.superclass.superclass
    => #<Class:Class>
    irb(main):002:0> c == c.superclass
    => true


    Any help in understanding this would be greatly appreciated!

    Thanks

    Neil
     
    Neil Curzon, Nov 8, 2007
    #1
    1. Advertising

  2. The JRuby discrepancies are very interesting and I don't know the
    answer. I e-mailed Charlie Nutter from JRuby and hopefully he'll chime
    in.

    > Something else I found weird is that when I go up the inheritance of a
    > String instance's metaclass in plain ruby, I quickly run into a loop:
    >
    > $ irb -r metaid
    > irb(main):001:0> c = String.new.metaclass.superclass.superclass
    > => #<Class:Class>
    > irb(main):002:0> c == c.superclass
    > => true
    >
    > Any help in understanding this would be greatly appreciated!


    This part at least I can explain. I think.

    In metaid.rb:

    def metaclass; class << self; self; end; end

    This means that when you use this method, you're just having the
    object open up its class and return that to you. What you're running
    into isn't really a loop so much as a fundamental particle. In the
    universe it may be true that you can subdivide any particle into
    smaller, "more fundamental" particles, but programming languages are
    much tidier than infinity, and sooner or later you get to the first
    turtle, and after that it's turtles all the way down. (I'm assuming
    you can understand me, and if you're using _why's guide to Ruby,
    there's a good chance I sound perfectly rational.) In real life every
    turtle is made up of smaller turtles; inside a programming language,
    when you hit the turtle, you're there.

    In a nutshell, I believe this means that just as the topmost class is
    Object, the topmost *class* is a Class:Class object. If that doesn't
    help, there's a simpler way to see it. Object is the fundamental
    class; all objects are ultimately Objects. Metaclasses have a parallel
    hierarchy, and all classes are ultimately instances of a Class:Class
    object - the object you've uncovered here. In a sense you've
    discovered the Holy Grail of the metaclass shadow world.

    (I'd probably be more coherent if I hadn't just spent about twenty
    minutes reading _why's stuff on Shoes.)

    --
    Giles Bowkett

    Blog: http://gilesbowkett.blogspot.com
    Portfolio: http://www.gilesgoatboy.org
    Tumblelog: http://giles.tumblr.com/
     
    Giles Bowkett, Nov 8, 2007
    #2
    1. Advertising

  3. Neil Curzon

    Phrogz Guest

    On Nov 7, 8:46 pm, Neil Curzon <> wrote:
    > Hi, all. I'm trying to understand chapter 24 of Programming Ruby.
    > I'm using "metaid.rb" from why the lucky stiff's site to help with the
    > examples. (http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html)
    >
    > Everything is pretty straightforward except for the diagrams of
    > inheritance of metaclasses. Figure 24.2 indicates that for a direct
    > subclass of Object, its metaclass's superclass should be Object's
    > metaclass. When I try this out in irb, I don't get the expected
    > result.


    Possibly this diagram will help:
    http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png
     
    Phrogz, Nov 8, 2007
    #3
  4. Hi --

    On Thu, 8 Nov 2007, Neil Curzon wrote:

    > Hi, all. I'm trying to understand chapter 24 of Programming Ruby.
    > I'm using "metaid.rb" from why the lucky stiff's site to help with the
    > examples. (http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html)
    >
    > Everything is pretty straightforward except for the diagrams of
    > inheritance of metaclasses. Figure 24.2 indicates that for a direct
    > subclass of Object, its metaclass's superclass should be Object's
    > metaclass. When I try this out in irb, I don't get the expected
    > result.
    >
    > $ irb -r metaid
    > irb(main):001:0> String.metaclass
    > => #<Class:String>
    > irb(main):002:0> String.metaclass.superclass
    > => #<Class:Class>
    > irb(main):003:0> String.metaclass.superclass == Object.metaclass
    > => false
    >
    > Surprisingly, when I try it in JRuby, I do get the expected result.
    >
    > $ jirb -r metaid
    > irb(main):001:0> String.metaclass
    > => #<Class:String>
    > irb(main):002:0> String.metaclass.superclass
    > => #<Class:Object>
    > irb(main):003:0> String.metaclass.superclass == Object.metaclass
    > => true


    It actually depends which version of Ruby you use. The superclass
    thing worked as expected in 1.8.2; then it stopped working (I'm not
    sure why); and in 1.9 it's working again. ("Not working" doesn't mean
    that the subclasses couldn't call the methods defined in their
    superclasses' singleton classes, just that the superclass thing itself
    was not in place.)

    $ cat super.rb
    class Object
    def singleton_class
    class << self; self; end
    end
    end

    p String.singleton_class.superclass == Object.singleton_class

    $ /usr/local/lib/ruby-1.8.2/bin/ruby -v super.rb
    ruby 1.8.2 (2004-12-25) [i686-linux]
    true
    $ ruby -v super.rb
    ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-linux]
    false
    $ /usr/local/lib/ruby-svn/bin/ruby -v super.rb
    ruby 1.9.0 (2007-11-07 patchlevel 0) [i686-linux]
    true


    David

    --
    Upcoming training by David A. Black/Ruby Power and Light, LLC:
    * Advancing With Rails, Edison, NJ, November 6-9
    * Advancing With Rails, Berlin, Germany, November 19-22
    * Intro to Rails, London, UK, December 3-6 (by Skills Matter)
    See http://www.rubypal.com for details!
     
    David A. Black, Nov 8, 2007
    #4
  5. On 11/8/07, David A. Black <> wrote:

    > It actually depends which version of Ruby you use. The superclass
    > thing worked as expected in 1.8.2; then it stopped working (I'm not
    > sure why); and in 1.9 it's working again. ("Not working" doesn't mean
    > that the subclasses couldn't call the methods defined in their
    > superclasses' singleton classes, just that the superclass thing itself
    > was not in place.)


    interesting, I didn't realize that this had changed in 1.9.

    Actually, it's not that anything isn't in place in 1.8, it's that the
    implementation of Class#superclass skips classes in the superclass
    chain, the same way that Object#class skips an instance singleton
    class if there is one, and the ancestors methods replaces the wrapper
    IClass nodes used to represent included modules in the behavior chain
    of an object into the modules themselves in the result.

    It's smoke and mirrors, and in the case of Ruby 1.9 it seems theres a
    little less smoke and mirrors in Class#superclass.


    --
    Rick DeNatale

    My blog on Ruby
    http://talklikeaduck.denhaven2.com/
     
    Rick DeNatale, Nov 8, 2007
    #5
  6. Neil Curzon

    Xavier Noria Guest

    On Nov 8, 2007, at 12:42 PM, Rick DeNatale wrote:

    > On 11/8/07, David A. Black <> wrote:
    >
    >> It actually depends which version of Ruby you use. The superclass
    >> thing worked as expected in 1.8.2; then it stopped working (I'm not
    >> sure why); and in 1.9 it's working again. ("Not working" doesn't mean
    >> that the subclasses couldn't call the methods defined in their
    >> superclasses' singleton classes, just that the superclass thing
    >> itself
    >> was not in place.)

    >
    > interesting, I didn't realize that this had changed in 1.9.
    >
    > Actually, it's not that anything isn't in place in 1.8, it's that the
    > implementation of Class#superclass skips classes in the superclass
    > chain, the same way that Object#class skips an instance singleton
    > class if there is one,


    Singleton classes are created on-demand behind the scenes?

    -- fxn
     
    Xavier Noria, Nov 8, 2007
    #6
  7. Hi --

    On Thu, 8 Nov 2007, Rick DeNatale wrote:

    > On 11/8/07, David A. Black <> wrote:
    >
    >> It actually depends which version of Ruby you use. The superclass
    >> thing worked as expected in 1.8.2; then it stopped working (I'm not
    >> sure why); and in 1.9 it's working again. ("Not working" doesn't mean
    >> that the subclasses couldn't call the methods defined in their
    >> superclasses' singleton classes, just that the superclass thing itself
    >> was not in place.)

    >
    > interesting, I didn't realize that this had changed in 1.9.
    >
    > Actually, it's not that anything isn't in place in 1.8, it's that the
    > implementation of Class#superclass skips classes in the superclass
    > chain, the same way that Object#class skips an instance singleton
    > class if there is one, and the ancestors methods replaces the wrapper
    > IClass nodes used to represent included modules in the behavior chain
    > of an object into the modules themselves in the result.


    By "superclass thing itself not in place" I just meant that you get
    false when you ask whether C's singleton class is the superclass of
    D's singleton class. So any documentation/books/etc. that describe it
    that way will seem wrong if you try it out in 1.8.6.

    > It's smoke and mirrors, and in the case of Ruby 1.9 it seems theres a
    > little less smoke and mirrors in Class#superclass.


    Always a good sign :)


    David

    --
    Upcoming training by David A. Black/Ruby Power and Light, LLC:
    * Advancing With Rails, Edison, NJ, November 6-9
    * Advancing With Rails, Berlin, Germany, November 19-22
    * Intro to Rails, London, UK, December 3-6 (by Skills Matter)
    See http://www.rubypal.com for details!
     
    David A. Black, Nov 8, 2007
    #7
  8. On 11/8/07, Xavier Noria <> wrote:
    > On Nov 8, 2007, at 12:42 PM, Rick DeNatale wrote:


    > > Actually, it's not that anything isn't in place in 1.8, it's that the
    > > implementation of Class#superclass skips classes in the superclass
    > > chain, the same way that Object#class skips an instance singleton
    > > class if there is one,

    >
    > Singleton classes are created on-demand behind the scenes?


    Yes, at least in 1.8, and I can't imagine why that would change.

    --
    Rick DeNatale

    My blog on Ruby
    http://talklikeaduck.denhaven2.com/
     
    Rick DeNatale, Nov 8, 2007
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Stephan Diehl

    question about metaclasses

    Stephan Diehl, Jun 30, 2003, in forum: Python
    Replies:
    2
    Views:
    339
    Stephan Diehl
    Jun 30, 2003
  2. Simon Burton

    metaclasses

    Simon Burton, Jul 28, 2003, in forum: Python
    Replies:
    5
    Views:
    403
    Simon Burton
    Jul 30, 2003
  3. Mike C. Fletcher

    Metaclasses presentation slides available...

    Mike C. Fletcher, Aug 28, 2003, in forum: Python
    Replies:
    3
    Views:
    342
    Alex Martelli
    Aug 29, 2003
  4. Simon Burton

    metaclasses for type comparison

    Simon Burton, Sep 11, 2003, in forum: Python
    Replies:
    5
    Views:
    311
    David Eppstein
    Sep 11, 2003
  5. Santiago Aguiar

    AOP and metaclasses

    Santiago Aguiar, Feb 20, 2004, in forum: Python
    Replies:
    2
    Views:
    333
    John Roth
    Feb 20, 2004
Loading...

Share This Page