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

T

Tony Arcieri

[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?
 
D

David Masover

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

Y. NOBUOKA

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

Josh Cheek

[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?
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
 
J

Jesús Gabriel y Galán

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

Intransition

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.

 
G

Gary Wright

=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
 
I

Intransition

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

Gary Wright

=20
=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=
 
T

Tony Arcieri

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

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

Intransition

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
 
G

Gary Wright

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?]
 
T

Tony Arcieri

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

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"?
 
G

Gary Wright

=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=
 
P

Peter Vandenabeele

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
 
T

Tony Arcieri

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

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
 
P

Peter Vandenabeele

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
 
R

Rick DeNatale

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
 
P

Peter Vandenabeele

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

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top