Singleton class, metaclass, eigenclass: what do they mean?

Discussion in 'Ruby' started by Tony Arcieri, Dec 2, 2010.

  1. Tony Arcieri

    Tony Arcieri Guest

    [Note: parts of this message were removed to make it a legal post.]

    Every time I think I have my head around what these terms mean I seem to run
    across someone with a completely different definition.

    My understanding was that the singleton class is what you obtain when you
    call self.class in instance scope, and that metaclass and eigenclass
    are interchangeable terms for what you obtain if you call class << self;
    self; end in instance scope.

    Is this correct? Do you have a different definition?

    --
    Tony Arcieri
    Medioh! A Kudelski Brand
    Tony Arcieri, Dec 2, 2010
    #1
    1. Advertising

  2. On Wednesday, December 01, 2010 11:25:35 pm Tony Arcieri wrote:
    > Every time I think I have my head around what these terms mean I seem to
    > run across someone with a completely different definition.
    >
    > My understanding was that the singleton class is what you obtain when you
    > call self.class in instance scope,


    That doesn't make sense. I'm curious to know where you got that definition,
    because when I call self.class, I just get the class, nothing "singleton"
    about it. Maybe that's useful to distinguish it from the metaclass or
    eigenclass, but I've always just called that the "class" of an object anyway.

    Ruby's standard library has an implementation of the Singleton pattern, in
    which there's a class which will only ever have one instance -- though this is
    Ruby, so you can always cheat -- so I suppose if you had an instance of a
    singleton class, calling self.class on that would give you a singleton class.

    But calling self.class on something else, even something that's been
    completely hacked up with extensions and even with directly modifying its
    metaclass as below, is still going to give you the same class as you'd get
    otherwise. That is, when I do this:

    a = 'foo'
    b = 'bar'

    class << b
    def to_sym
    :hacked_bar
    end
    end

    module C
    def has_c?
    true
    end
    end
    b.extend C

    Pretty much anything I do to b other than manually overriding the class
    method, and I still can't tell the difference between a.class and b.class.
    Both return String, and in every way I've cared to test, it's, well, just
    String:

    a.class # String
    b.class # String
    a.object_id == b.object_id # true
    a.object_id == String.object_id # true

    This is Ruby, so maybe I'm missing something, but it really does just seem to
    be the class. Is that right?

    > and that metaclass and eigenclass
    > are interchangeable terms for what you obtain if you call class << self;
    > self; end in instance scope.


    This is correct, as far as I know. Note that you don't need to do this with
    'self' necessarily -- you could do:

    class << some_object; self; end

    That would give you the metaclass of some_object.

    I tend to use _why's metaid anyway.
    David Masover, Dec 2, 2010
    #2
    1. Advertising

  3. Tony Arcieri

    Y. NOBUOKA Guest

    > My understanding was that the singleton class is what you obtain when you
    > call self.class in instance scope


    I think it is not a singleton class, but a normal class.

    > metaclass and eigenclass are interchangeable terms for
    > what you obtain if you call class << self; self; end in instance scope.


    This is just an eigenclass, and I understand that the term
    "eigenclass" is interchangeable with "singleton class".
    Please see the following example:

    class Object
    # this method return the singleton class of the receiver
    def singleton_class
    class << self; self end
    end
    end

    # obtain the singleton class of a String object
    sc = "aaaa".singleton_class
    p sc #=> #<Class:#<String:0x00000001442a50>>
    begin
    # if you try to create a instance of a singleton class...
    sc.new # raise error!!
    rescue => err
    puts err #=> can't create instance of singleton class
    # (ruby 1.9.1)
    #=> can't create instance of virtual class
    # (ruby 1.8)
    # this error message tell us that +sc+ is
    # an singleton class
    end

    I don't know the term "metaclass" is interchangeable with the term
    "eigenclass"... I think a metaclass is a Class object or a singleton
    class of a Class object, but I'm not sure.

    --
    nobuoka
    Y. NOBUOKA, Dec 2, 2010
    #3
  4. Tony Arcieri

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Wed, Dec 1, 2010 at 11:25 PM, Tony Arcieri <>wrote:

    > Every time I think I have my head around what these terms mean I seem to
    > run
    > across someone with a completely different definition.
    >
    > My understanding was that the singleton class is what you obtain when you
    > call self.class in instance scope, and that metaclass and eigenclass
    > are interchangeable terms for what you obtain if you call class << self;
    > self; end in instance scope.
    >
    > Is this correct? Do you have a different definition?
    >
    >

    I take all three to mean the same thing: the object's own personal class. It
    has only one instance, which is the object.

    Or, in code:

    class << obj
    # now we are in obj's metaclass / eigenclass / singleton class
    end

    I think the different names exist for historical reasons, I personally use
    "metaclass" because that is what _why used in Dwemthy's Array
    http://mislav.uniqpath.com/poignant-guide/dwemthy/ but I think the name
    "eigenclass" sounds badass (reminiscent of steampunk), so maybe I'll start
    using it, instead :p
    Josh Cheek, Dec 2, 2010
    #4
  5. On Thu, Dec 2, 2010 at 8:27 AM, Josh Cheek <> wrote:
    > On Wed, Dec 1, 2010 at 11:25 PM, Tony Arcieri <>wr=

    ote:
    >
    >> Every time I think I have my head around what these terms mean I seem to
    >> run
    >> across someone with a completely different definition.
    >>
    >> My understanding was that the singleton class is what you obtain when yo=

    u
    >> call self.class in instance scope, and that metaclass and eigenclass
    >> are interchangeable terms for what you obtain if you call class << self;
    >> self; end in instance scope.
    >>
    >> Is this correct? Do you have a different definition?
    >>
    >>

    > I take all three to mean the same thing: the object's own personal class.=

    It
    > has only one instance, which is the object.
    >
    > Or, in code:
    >
    > class << obj
    > =A0# now we are in obj's metaclass / eigenclass / singleton class
    > end


    I agree with this. For me they mean the same thing.

    > I think the different names exist for historical reasons, I personally us=

    e
    > "metaclass" because that is what _why used in Dwemthy's Array
    > http://mislav.uniqpath.com/poignant-guide/dwemthy/ but I think the name
    > "eigenclass" sounds badass (reminiscent of steampunk), so maybe I'll star=

    t
    > using it, instead :p


    I use "singleton class" :).

    Jesus.
    Jesús Gabriel y Galán, Dec 2, 2010
    #5
  6. Tony Arcieri

    Intransition Guest

    On Dec 2, 12:25=A0am, Tony Arcieri <> wrote:
    > Every time I think I have my head around what these terms mean I seem to =

    run
    > across someone with a completely different definition.
    >
    > My understanding was that the singleton class is what you obtain when you
    > call self.class in instance scope, and that metaclass and eigenclass
    > are interchangeable terms for what you obtain if you call class << self;
    > self; end in instance scope.
    >
    > Is this correct? Do you have a different definition?


    Technically they are all the same.


    > --
    > Tony Arcieri
    > Medioh! A Kudelski Brand
    Intransition, Dec 2, 2010
    #6
  7. Tony Arcieri

    Gary Wright Guest

    On Dec 2, 2010, at 11:47 AM, Intransition wrote:
    > On Dec 2, 12:25 am, Tony Arcieri <> wrote:
    >> Every time I think I have my head around what these terms mean I seem =

    to run
    >> across someone with a completely different definition.
    >>=20
    >> My understanding was that the singleton class is what you obtain when =

    you
    >> call self.class in instance scope, and that metaclass and eigenclass
    >> are interchangeable terms for what you obtain if you call class << =

    self;
    >> self; end in instance scope.
    >>=20
    >> Is this correct? Do you have a different definition?

    >=20
    > Technically they are all the same.


    Perhaps it was the original question that was confusing but they
    are not all the same. There are two different situations in the
    examples given by the original poster:
    =20
    1) object.class in any context is the class of which 'object' is
    an instance

    self.class is just a particular example of this for 'self'

    2) =20

    Ruby 1.9.2:=20
    object.singleton_class in any context is the (perhaps newly
    created) singleton class for 'object'

    self.singleton_class is again just a particular example
    of this for 'self'

    Prior to Ruby 1.9.2:
    The expression, (class <<object; self; end), was needed to
    access the singleton objects as there was no standard method
    that returned a reference to the singleton class.

    self.class and self.singleton_class are both classes but they
    each play their own separate role in Ruby's method lookup
    process.

    There has been a long running debate in the Ruby community as to
    what to name the object returned by (class <<object; self; end) but
    with the introduction of Object#singleton_class in 1.9.2 that debate
    is effectively over.

    The most common alternative names were eigenclass, metaclass, and
    perhaps virtual class as well as a long list of other variations.
    Each one had its pros/cons but "singleton class" is the one that
    Matz settled on in 1.9.2.

    Gary Wright
    Gary Wright, Dec 2, 2010
    #7
  8. Tony Arcieri

    Intransition Guest

    On Dec 2, 12:23=A0pm, Gary Wright <> wrote:
    > On Dec 2, 2010, at 11:47 AM, Intransition wrote:
    >
    > > On Dec 2, 12:25 am, Tony Arcieri <> wrote:
    > >> Every time I think I have my head around what these terms mean I seem =

    to run
    > >> across someone with a completely different definition.

    >
    > >> My understanding was that the singleton class is what you obtain when =

    you
    > >> call self.class in instance scope, and that metaclass and eigenclass
    > >> are interchangeable terms for what you obtain if you call class << sel=

    f;
    > >> self; end in instance scope.

    >
    > >> Is this correct? Do you have a different definition?

    >
    > > Technically they are all the same.

    >
    > Perhaps it was the original question that was confusing but they
    > are not all the same. =A0


    The terms singleton class, eigenclass and metaclass are. Which I
    believe was the question.
    Intransition, Dec 2, 2010
    #8
  9. Tony Arcieri

    Gary Wright Guest

    On Dec 2, 2010, at 1:50 PM, Intransition wrote:

    >=20
    >=20
    > On Dec 2, 12:23 pm, Gary Wright <> wrote:
    >> On Dec 2, 2010, at 11:47 AM, Intransition wrote:
    >>=20
    >>> On Dec 2, 12:25 am, Tony Arcieri <> wrote:
    >>>> Every time I think I have my head around what these terms mean I =

    seem to run
    >>>> across someone with a completely different definition.

    >>=20
    >>>> My understanding was that the singleton class is what you obtain =

    when you
    >>>> call self.class in instance scope, and that metaclass and =

    eigenclass
    >>>> are interchangeable terms for what you obtain if you call class << =

    self;
    >>>> self; end in instance scope.

    >>=20
    >>>> Is this correct? Do you have a different definition?

    >>=20
    >>> Technically they are all the same.

    >>=20
    >> Perhaps it was the original question that was confusing but they
    >> are not all the same. =20

    >=20
    > The terms singleton class, eigenclass and metaclass are. Which I
    > believe was the question.
    >=20


    As I said, the original question is somewhat vague. I read it as
    asking if all of the following are the same:

    self.class in instance scope =3D singleton class
    metaclass =3D singleton class
    eigenclass =3D singleton class

    and that is not correct (i.e. self.class is not a singleton class).

    Gary Wright=
    Gary Wright, Dec 2, 2010
    #9
  10. Tony Arcieri

    Tony Arcieri Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Thu, Dec 2, 2010 at 11:50 AM, Intransition <> wrote:

    > The terms singleton class, eigenclass and metaclass are. Which I
    > believe was the question.
    >


    Yeah, thanks for the clarification everyone. I talked to a Ruby implementer
    who agrees these three terms are interchangeable.

    The confusion arose for me from "singleton methods", whose name comes from
    things like rb_define_singleton_method() (in the C API) and the
    singleton_method_callback.

    I still see a lot of confusion as to what to call the object which
    represents a class. "Singleton class" made sense to me in that context...
    there is only one object, its class is Class, and as far as I can tell
    singleton methods are instance-specific behaviors of this object.

    So what is the proper term for the object (with "singleton methods") that
    represents a class but is not its singleton class/metaclass/eigenclass?

    How fucking confusing...

    --
    Tony Arcieri
    Medioh! A Kudelski Brand
    Tony Arcieri, Dec 2, 2010
    #10
  11. Tony Arcieri

    Intransition Guest

    On Dec 2, 5:50=A0pm, Tony Arcieri <> wrote:
    > On Thu, Dec 2, 2010 at 11:50 AM, Intransition <> wrote=

    :
    > > The terms singleton class, eigenclass and metaclass are. Which I
    > > believe was the question.

    >
    > Yeah, thanks for the clarification everyone. I talked to a Ruby implement=

    er
    > who agrees these three terms are interchangeable.
    >
    > The confusion arose for me from "singleton methods", whose name comes fro=

    m
    > things like rb_define_singleton_method() (in the C API) and the
    > singleton_method_callback.
    >
    > I still see a lot of confusion as to what to call the object which
    > represents a class. "Singleton class" made sense to me in that context...
    > there is only one object, its class is Class, and as far as I can tell
    > singleton methods are instance-specific behaviors of this object.
    >
    > So what is the proper term for the object (with "singleton methods") that
    > represents a class but is not its singleton class/metaclass/eigenclass?
    >
    > How fucking confusing...


    http://www.hokstad.com/ruby-object-model.html
    Intransition, Dec 2, 2010
    #11
  12. Tony Arcieri

    Tony Arcieri Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Thu, Dec 2, 2010 at 4:18 PM, Intransition <> wrote:

    > http://www.hokstad.com/ruby-object-model.html
    >


    That seems to refer to it as a "Class object"... my question is why does the
    Class object seem to have singleton methods?

    --
    Tony Arcieri
    Medioh! A Kudelski Brand
    Tony Arcieri, Dec 2, 2010
    #12
  13. Tony Arcieri

    Gary Wright Guest

    On Dec 2, 2010, at 6:27 PM, Tony Arcieri wrote:

    > On Thu, Dec 2, 2010 at 4:18 PM, Intransition <> wrote:
    >
    >> http://www.hokstad.com/ruby-object-model.html
    >>

    >
    > That seems to refer to it as a "Class object"... my question is why does the
    > Class object seem to have singleton methods?


    Because some classes have behavior that is unique to the class.
    File and Time are both objects which are instances of Class but
    they respond to a different set of methods. For example:

    File.exists? is a class method.
    Time.now is a class method.

    For an object to have per-object methods, the methods are defined
    in the object's singleton class:

    ruby-1.9.2-p0 > Time.singleton_class.instance_methods(false)
    => [:now, :at, :utc, :gm, :local, :mktime, :_load]
    ruby-1.9.2-p0 > File.singleton_class.instance_methods(false)

    => [:directory?, :exist?, :exists?, :readable?, :readable_real?, :world_readable?, :writable?, :writable_real?, :world_writable?, :executable?, :executable_real?, :file?, :zero?, :size?, :size, :eek:wned?, :grpowned?, :pipe?, :symlink?, :socket?, :blockdev?, :chardev?, :setuid?, :setgid?, :sticky?, :identical?, :stat, :lstat, :ftype, :atime, :mtime, :ctime, :utime, :chmod, :chown, :lchmod, :lchown, :link, :symlink, :readlink, :unlink, :delete, :rename, :umask, :truncate, :expand_path, :absolute_path, :realpath, :realdirpath, :basename, :dirname, :extname, :path, :split, :join, :fnmatch, :fnmatch?]
    Gary Wright, Dec 2, 2010
    #13
  14. Tony Arcieri

    Tony Arcieri Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Thu, Dec 2, 2010 at 4:55 PM, Gary Wright <> wrote:

    > Because some classes have behavior that is unique to the class.
    >


    Earlier I asked how this was implemented... apparently "class objects" have
    instance-specific behavior in their "singleton class" which takes the form
    of "singleton methods"?

    --
    Tony Arcieri
    Medioh! A Kudelski Brand
    Tony Arcieri, Dec 2, 2010
    #14
  15. Tony Arcieri

    Gary Wright Guest

    On Dec 2, 2010, at 6:59 PM, Tony Arcieri wrote:

    > On Thu, Dec 2, 2010 at 4:55 PM, Gary Wright <> wrote:
    >=20
    >> Because some classes have behavior that is unique to the class.
    >>=20

    >=20
    > Earlier I asked how this was implemented... apparently "class objects" =

    have
    > instance-specific behavior in their "singleton class" which takes the =

    form
    > of "singleton methods"?


    Yes, but this is not special behavior for class objects.

    Per-object behavior in Ruby is implemented by adding methods to the =
    singleton
    class for the object. It doesn't matter if the object is a string, an =
    array,
    or a class. The per-object methods (i.e. singleton methods) are all =
    implemented
    in the same way, via instance methods of the singleton class for the =
    object.

    If the object happens to be a class object then those singleton methods =
    are
    commonly known as 'class methods' but that is just a naming convention.

    Gary Wright=
    Gary Wright, Dec 3, 2010
    #15
  16. On Fri, Dec 3, 2010 at 5:05 AM, Gary Wright <> wrote:
    > On Dec 2, 2010, at 6:59 PM, Tony Arcieri wrote:
    >> On Thu, Dec 2, 2010 at 4:55 PM, Gary Wright <> wrote:

    ...
    >> Earlier I asked how this was implemented... apparently "class objects" h=

    ave
    >> instance-specific behavior in their "singleton class" which takes the fo=

    rm
    >> of "singleton methods"?

    >
    > Yes, but this is not special behavior for class objects.
    >
    > Per-object behavior in Ruby is implemented by adding methods to the singl=

    eton
    > class for the object. =C2=A0It doesn't matter if the object is a string, =

    an array,
    > or a class. =C2=A0The per-object methods (i.e. singleton methods) are all=

    implemented
    > in the same way, via instance methods of the singleton class for the obje=

    ct.
    >
    > If the object happens to be a class object then those singleton methods a=

    re
    > commonly known as 'class methods' but that is just a naming convention.


    For me, it was the book "Advanced Rails" by Brad Ediger (O'Reilly) that fin=
    ally
    got me to understand how this really fits together. Already on page 12 to 1=
    5,
    you get an excellent explanation over why it works the way it does (and it'=
    s
    brilliant in it's simplicity, once you get it :)

    Peter
    Peter Vandenabeele, Dec 3, 2010
    #16
  17. Tony Arcieri

    Tony Arcieri Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Fri, Dec 3, 2010 at 1:17 AM, Peter Vandenabeele
    <>wrote:

    > For me, it was the book "Advanced Rails" by Brad Ediger (O'Reilly) that
    > finally
    > got me to understand how this really fits together. Already on page 12 to
    > 15,
    > you get an excellent explanation over why it works the way it does (and
    > it's
    > brilliant in it's simplicity, once you get it :)



    Is there some overall, grand unifying pattern I'm missing then? Because when
    I look at Ruby method dispatch it seems a bit like an ad hoc mess

    --
    Tony Arcieri
    Medioh! Kudelski
    Tony Arcieri, Dec 4, 2010
    #17
  18. On Sat, Dec 4, 2010 at 4:37 AM, Tony Arcieri <> wrote:
    > Is there some overall, grand unifying pattern I'm missing then? Because when
    > I look at Ruby method dispatch it seems a bit like an ad hoc mess


    If I understand correctly (and I would welcome corrections), the pattern
    for method lookup is:

    Looking up "instance methods" :

    * for an object that is not a class (object.class != Class)
    * if there is an object.singleton_class
    * search in the (instance) methods of this object.singleton_class
    else
    * search in the (instance) methods of the object.class
    * then recursively follow the super pointer upwards from there
    * for the object.singleton_class, the super pointer will point
    to object.class
    * for "normal" classes, the super pointer will point to the
    class from which this "normal" class inherits or optionally
    to an ICLASS that is a proxy for an included module
    * until we reach BasicObject

    Looking up "class methods":

    * for an object that is a class (object.class == Class)
    * there is always an object.singleton_class
    * search in the (instance) methods of this object.singleton_class
    * then recursively follow the super pointer upwards from there
    * for the object.singleton_class and higher-up singleton classes,
    the super pointer will point to object.superclass.singletonclass,
    thus forming a parallel super-chain of singleton classes
    (until #<Class:BasicObject> is reached, then we jump to Class)
    * for "normal" classes, the super pointer will point to the
    class from which this "normal" class inherits or optionally
    to an ICLASS that is a proxy for an included module
    * until we reach BasicObject


    * Note 1: If I understand correctly, for an object that is not
    a class, the singleton_class is not prepared a priori, but
    is generated at the time when it is called.

    * Note 2: the ruby 'superclass' method does not always show the
    immediate thing pointed to by "super". In Ruby 1.9.2, I believe
    it shows the next thing in the super-chain that is a Class, but
    in Ruby 1.8.7 superclass on a singleton class shows Class,
    while there are still intermediate singleton classes, e.g.
    #<Class:Object>. ICLASS's for modules can be in the
    super-chain as well, but are also not shown by the superclass
    function (but these can be discovered with
    self.included_modules - self.superclass.included_modules).

    References:
    * "Advanced Rails" (Brad Ediger), O'Reilly
    * http://www.klankboomklang.com/2007/10/05/the-metaclass/
    (has a nice graphic of the parallel super-chain formed by singleton classes)

    Corrections welcome,

    Peter

    Example for instance d of class D, without a singleton class:
    =============================================================

    $ irb
    ruby-1.9.2-head > class D < Object; end
    => nil
    ruby-1.9.2-head > d= D.new
    => #<D:0x84b05e8>
    ruby-1.9.2-head > d.class
    => D ## this shows that d is _not_ a class
    ruby-1.9.2-head > d.singleton_class
    => #<Class:#<D:0x84b05e8>> ## is created ad-hoc
    ruby-1.9.2-head > d.singleton_class.instance_methods(false)
    => [] ## but has no methods, so search in D
    ruby-1.9.2-head > D.superclass
    => Object
    ruby-1.9.2-head > D.superclass.included_modules -
    D.superclass.superclass.included_modules
    => [Kernel] # Object has the Kernel module included, so that will be
    searched also
    ruby-1.9.2-head > D.superclass.superclass
    => BasicObject
    ruby-1.9.2-head > D.superclass.superclass.superclass
    => nil
    ruby-1.9.2-head > D.ancestors
    => [D, Object, Kernel, BasicObject]

    Example for instance e of class E, with a singleton class:
    ==========================================================

    ruby-1.9.2-head > class E < Object; end
    => nil
    ruby-1.9.2-head > e = E.new
    => #<E:0x8960d68>
    ruby-1.9.2-head > e2 = E.new
    => #<E:0x896bbc8>
    ruby-1.9.2-head > class << e # opening the singleton class of _object_ e
    ruby-1.9.2-head ?> def my_singleton_method
    ruby-1.9.2-head ?> "my_singleton_method, defined in e.singleton_class"
    ruby-1.9.2-head ?> end
    ruby-1.9.2-head ?> end
    => nil
    ruby-1.9.2-head > e.my_singleton_method
    => "my_singleton_method, defined in e.singleton_class"
    ruby-1.9.2-head > e2.my_singleton_method ## no luck, the singleton
    method is only for e
    NoMethodError: undefined method `my_singleton_method' for #<E:0x896bbc8>
    from (irb):25
    from /home/peterv/.rvm/rubies/ruby-1.9.2-head/bin/irb:16:in `<main>'
    ruby-1.9.2-head > e.class
    => E
    ruby-1.9.2-head > e.singleton_class
    => #<Class:#<E:0x8960d68>>
    ruby-1.9.2-head > e.singleton_class.instance_methods(false)
    => [:my_singleton_method]
    ruby-1.9.2-head > E.superclass
    => Object
    ruby-1.9.2-head > E.superclass.included_modules -
    D.superclass.superclass.included_modules
    => [Kernel]
    ruby-1.9.2-head > E.superclass.superclass
    => BasicObject
    ruby-1.9.2-head > E.superclass.superclass.superclass
    => nil
    ruby-1.9.2-head > E.ancestors
    => [E, Object, Kernel, BasicObject]


    Example with classes (Object, A, B, C) with singleton classes:
    ==============================================================

    First this class definition code:

    class Object
    class << Object
    def my_class_method_0
    "my_class_method_0, defined in Object.singleton_class"
    end
    def my_class_method_1
    "my_class_method_1, defined in Object.singleton_class"
    end
    def my_class_method_2
    "my_class_method_2, defined in Object.singleton_class"
    end
    end
    end

    class A < Object
    class << A
    def my_class_method_0
    "my_class_method_0, defined in A.singleton_class"
    end
    def my_class_method_1
    "my_class_method_1, defined in A.singleton_class"
    end
    # NOT defined my_class_method_2
    end
    def my_instance_method_in_A
    "instance method, defined in A"
    end
    end

    class B < A
    class << B
    def my_class_method_0
    "my_class_method_0, defined in B.singleton_class"
    end
    # NOT defined my_class_method_1
    # NOT defined my_class_method_2
    end
    end

    class C < B
    # singleton class was not opened
    end

    Results in:

    ruby-1.9.2-head > B.class
    => Class ## this shows that B is a class
    ruby-1.9.2-head > B.my_class_method_0 ## in B.singleton_class
    => "my_class_method_0, defined in B.singleton_class"
    ruby-1.9.2-head > B.my_class_method_1
    => "my_class_method_1, defined in A.singleton_class"
    ## in B.singleton_class.superclass == A.singleton_class
    ruby-1.9.2-head > B.my_class_method_2
    => "my_class_method_2, defined in Object.singleton_class"
    ## in B.singleton_class.superclass.superclass == Object.singleton_class
    ruby-1.9.2-head > C.my_class_method_0 ## in C.singleton_class.superclass
    => "my_class_method_0, defined in B.singleton_class"
    ruby-1.9.2-head > A.my_class_method_0 ## in A.singleton_class
    => "my_class_method_0, defined in A.singleton_class"
    ruby-1.9.2-head > B.singleton_class.instance_methods(false)
    => [:my_class_method_0]
    ruby-1.9.2-head > A.singleton_class.instance_methods(false)
    => [:my_class_method_0, :my_class_method_1]
    ruby-1.9.2-head > super_chain = [] ; sc = C.singleton_class
    => #<Class:C>
    ruby-1.9.2-head > while sc
    ruby-1.9.2-head ?> super_chain << sc
    ruby-1.9.2-head ?> sc = sc.superclass
    ruby-1.9.2-head ?> end
    => nil
    ruby-1.9.2-head > super_chain
    => [#<Class:C>, #<Class:B>, #<Class:A>, #<Class:Object>,
    #<Class:BasicObject>, Class, Module, Object, BasicObject]

    Note: this last result does not show the modules (e.g. Kernel) that are also
    included in the internal super-chain but are not shown by the ruby
    superclass method
    Peter Vandenabeele, Dec 4, 2010
    #18
  19. On Sat, Dec 4, 2010 at 2:56 PM, Peter Vandenabeele
    <> wrote:
    > On Sat, Dec 4, 2010 at 4:37 AM, Tony Arcieri <> wr=

    ote:
    >> Is there some overall, grand unifying pattern I'm missing then? Because =

    when
    >> I look at Ruby method dispatch it seems a bit like an ad hoc mess

    >
    > If I understand correctly (and I would welcome corrections), the pattern
    > for method lookup is:
    >
    > Looking up "instance methods" :
    >
    > * for an object that is not a class (object.class !=3D Class)

    [snip]
    > =C2=A0* until we reach BasicObject
    >
    > Looking up "class methods":
    >
    > * for an object that is a class (object.class =3D=3D Class)
    > =C2=A0* there is always an object.singleton_class

    [snip]

    There's a much simpler explanation IMHO.

    To send a message to an object, (this describes MRI, but other
    implementations are probably similar). The following pseudo code uses
    variable names I've made up.

    set receiver to the object
    set method selector to the symbol representing the method name
    set search_klass to receiver -> klass
    set method to nil
    while method =3D=3D nil && search_behavior !=3D nil
    unless (method =3D search_klass.mtab[method_selector])
    search_klass =3D search_klass.super
    end
    end

    if method =3D=3D nil
    send method_missing(method_selector *args, &block) to receiver #
    this is done 'recursively' so the search for method_missing starts
    with the receiver's klass.
    end

    There's no need to treat class method or singleton methods separately.
    The difference is how the klass -> superclass chains are set up.

    If an object has a singleton class then the objects klass field points
    to the singleton 'class' and the singleton 'class' has its super field
    set to point to the original class.

    Class methods are just singleton methods on the object which
    represents that class, class methods are 'inherited' because the
    superclass of the singleton class is set to point to the singleton
    class of the class' superclass.

    The 'things' pointed to by klass pointers are either:

    1) class objects (like Array, Hash, Object etc) if they are marked by
    a flag that they are 'virtual' then they are not returned by methods
    like class, superclass, ancestors, etc. Singleton classes are so
    marked this applies to singleton classes of individual objects or
    singleton classes of Classes.

    or two
    2) proxy 'classes' used to represent modules in the inheritance chain,
    these are marked as both 'virtual' and 'proxy' IIRC, and point ot the
    same mtab as the module they represent. This allows modules to be
    included in multiple klass chains and have changes to the methods of
    the module be reflected where ever the module is included, or used to
    extend an object.

    Module#include inserts a proxy chain starting with a proxy for the
    module being included, and followed by proxies for each module
    included by that module, etc. before the current 'superclass' of the
    class or module being sent #include, again Modules have 'hidden'
    superclasses at the implementation level actually these are visible
    via the Module#ancestors method.

    As an aside, which is probably more apropos the title of this thread.
    I don't personally consider singleton_class, eigenclass, and metaclass
    to be equivalent terms.

    In particular I reserved the term metaclass to be the 'singleton'
    class of a class object. I put singleton in quotes here because,
    although MRI uses the singleton class mechanism to implement
    metaclasses, metaclasses are 'less' singleton when you consider that
    'singleton' methods which are found in the mtab of the object's
    singleton class, are not shared by any other object, class methods
    which found in the mtab of the metaclass ARE shared in the case where
    the class in question has one or more subclasses.

    The etymology of the word metaclass is similar to that of metalanguage

    meta- (also met- before a vowel or h)
    combining form
    1 denoting a change of position or condition : metamorphosis | metathesis.
    2 denoting position behind, after, or beyond: : metacarpus.
    3 denoting something of a higher or second-order kind : metalanguage | meto=
    nym.

    i.e. the third definition of meta here.

    and

    metalanguage |=CB=88met=C9=99=CB=8Cla ng (g)wij|
    noun
    a form of language or set of terms used for the description or
    analysis of another language. Compare with object language (sense 1).
    =E2=80=A2 Logic a system of propositions about propositions.

    So as I define it (and as is normal in most OO languages) a metaclass
    is a form of class used to describe a class. A singleton class used
    to describe singleton methods of an object is NOT a metaclass but
    rather a singleton CLASS for that object, which inherits from the
    objects original class, and is hidden from Ruby's reflection methods
    because that 'virtual' bit is set.

    IMHO, _why sowed a seed of confusion when he used metaclass in a way
    which conflicts with the common definition, in the poignant guide.


    > * Note 1: If I understand correctly, for an object that is not
    > =C2=A0a class, the singleton_class is not prepared a priori, but
    > =C2=A0is generated at the time when it is called.


    This is true, although it's really an implementation detail. I don't
    think you can detect this from Ruby without the aid of a C extension
    to let you look for a singleton class without having one created
    automatically as soon as you ask for it with, say class <<
    self;self;end

    I suppose I should really turn this into a blog article.

    --=20
    Rick DeNatale

    Blog: http://talklikeaduck.denhaven2.com/
    Github: http://github.com/rubyredrick
    Twitter: @RickDeNatale
    WWR: http://www.workingwithrails.com/person/9021-rick-denatale
    LinkedIn: http://www.linkedin.com/in/rickdenatale
    Rick DeNatale, Dec 5, 2010
    #19
  20. On Sun, Dec 5, 2010 at 4:54 PM, Rick DeNatale <> wro=
    te:
    > There's a much simpler explanation IMHO.

    ...
    Thanks for the detailed explanation.

    > The 'things' pointed to by klass pointers are either:


    Could this be a typo where you intended to say 'super' pointers?

    > 1) class objects (like Array, Hash, Object etc) =C2=A0if they are marked =

    by
    > a flag that they are 'virtual' then they are not returned by methods
    > like class, superclass, ancestors, etc.


    From my findings:

    * the ancestors and the class method always hide it (as you write above)
    * the 'superclass' method _does_ return the first singleton classes
    pointed to by 'super'

    <code>
    $ irb
    ruby-1.9.2-head > class A < Object; end
    =3D> nil
    ruby-1.9.2-head > A.singleton_class
    =3D> #<Class:A>
    ruby-1.9.2-head > A.singleton_class.superclass
    =3D> #<Class:Object>
    </code>

    > I suppose I should really turn this into a blog article.


    Those 2 posts are also relevant:
    * http://www.klankboomklang.com/2007/10/05/the-metaclass/
    * http://www.hokstad.com/ruby-object-model.html

    Thanks again (I think I get it now, next step is to look it up in the C cod=
    e)

    Peter
    Peter Vandenabeele, Dec 5, 2010
    #20
    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. ironfroggy
    Replies:
    16
    Views:
    438
    Michele Simionato
    Jun 3, 2005
  2. Dorren
    Replies:
    4
    Views:
    118
    Dorren
    Jun 4, 2007
  3. Paul McMahon
    Replies:
    3
    Views:
    206
    David A. Black
    Jun 9, 2008
  4. JP Billaud

    Class Variables in EigenClass

    JP Billaud, Mar 7, 2011, in forum: Ruby
    Replies:
    10
    Views:
    265
    Sony S.
    Mar 23, 2011
  5. Steven D'Aprano

    Metaclass of a metaclass

    Steven D'Aprano, Jun 5, 2012, in forum: Python
    Replies:
    1
    Views:
    305
Loading...

Share This Page