Rick, Robert,
Thanks for your helpful replies. I have just introduced myself to Ruby
in the last couple of weeks by reading The Ruby P.ming Language, so
I’m still trying to pin some concepts. One thing I have found
interesting in looking things up online is that it’s not uncommon to
refer to C-level constructs in MRI when discussing language semantics.
(I personally would prefer to restrict myself to what’s observable from
sample Ruby code.)
Firstly, Robert, you have used “is_a?” in your example. This tests for
(direct or indirect) conformance. I quibbled with the notion that the
ordinary object was an instance of the eigenclass. The normal usage of
the term “instance” to mean “direct instance” is reflected in the
semantics of Ruby’s “instance_of?” method. Using this method, we could
extend your sample code as follows:
irb> a.instance_of? s
=> false
irb> a.instance_of? Object
=> true
This is what I meant, and to me, this is significant. One of my
reference points in reading about Ruby was Smalltalk, which has the
notion of a metaclass. In Smalltalk the concept is clear. (Indeed, the
only reasonable meaning for the term metaclass is “a class whose
instances are classes”.) In Ruby, some people contend that eigenclass
and metaclass are synonyms, which seems to me to confuse two distinct
notions. In the interests of conceptual clarity, here’s my take on the
two notions. (Feel free to poke holes in this if it’s totally
upside-down or otherwise mistaken.)
(a) Eigenclass
Ruby allows for per-instance methods (deliberately avoiding the more
common term as it’s overloaded with a well-known pattern). The
conceptual container for these per-instance methods is the object’s
eigenclass. The precise implementation of this notion in the reference
notion should be immaterial. What is important is that a decision was
made to reify the notion by providing language syntax to open it up, as
follows:
class << myObject
This allows for dealing with several per-instance methods together. More
to the point, if this syntax was not part of the language, eigenclasses
would be purely an implementation notion and have no correspondence in
Ruby code.
(b) Metaclass
To me, there is only one metaclass in Ruby, namely class Class. (By any
reasonable definition of the term metaclass.) It seems to me mistaken to
equate the terms metaclass and eigenclass. For one thing, every object
in Ruby has an eigenclass (not just class objects). Secondly, even if we
restrict our consideration purely to eigenclasses of class objects,
these don’t really qualify as metaclasses either. In Smalltalk, every
class object is a (direct) instance of a metaclass. In Ruby, class
objects are not (direct) instances of any eigenclass; they are all
(direct) instances of class Class.
From this, it would seem to me that the term metaclass should not be
used in Ruby. (Flanagan and Matz possibly agree as they seem to largely
avoid the term in their book).
I would, however, agree with Rick about the muddiness surrounding
superclasses. For example, the example on page 294-295-296 of the book
uses the eigenclass to wrap tracing code around methods. In doing so,
they use a call to super to access the original implementation. Now
super, by the definition on page 238, “invokes a method with the same
name as the current one, in the superclass of the current class”. So,
for this to work, the superclass of the eigenclass needs to be the
original class. In other words, let’s say we have a class called X, an
instance of that class called x and let’s say the eigenclass of x is e.
The method on page 294 will work if the superclass of e is X. (Because
that’s where the original implementation is defined.) However, this is
not the case. The superclass of the eigenclass is not the original
class. It is the eigenclass of the original class. Finally, note that in
saying “the superclass of the eigenclass is not the original class”, it
would appear that it was at one stage. According to Paolo Nusco
Perrotta, at least some implementations of 1.8.2 and 1.9 had this
behaviour:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/248178
(link repeated from my original post).
Regards,
Danny.