Type/Class Unification in Ruby

Greg Ewing greg.ewing at compaq.com
Wed Nov 17 11:54:00 CET 1999


I've been looking into the way types and classes are
unified in Ruby.

As I mentioned earlier, all objects in Ruby are associated
with an object of class Class, which plays the role of
both the PyTypeObject and PyClassObject. Consequently,
it is possible to define subclasses of any of the built
in types and add or override methods. It's even possible
to add instance variables -- I'll explain how that works
below.

Each of the built-in types is represented by a unique
C structure, as in Python. Therefore it is important that
when a subclass of a built-in class is instantiated, the
right kind of C structure is created, since all the
built-in methods of its superclass expect to get that
kind of structure.

This is guaranteed by two characteristics of Ruby that
differ from Python:

1) Instantiation of a class is done by calling a class
method of that class. (Ruby has real class methods and
variables, like Smalltalk. In fact, Ruby's internals are
very Smalltalk-like in many ways.)

2) A class can only inherit from at most one other
class.

The only methods which actually create C structures are
the built-in instantiation methods of the built-in
classes, so even if you define your own instantiation
method in your subclass, it eventually has to call a
built-in one somewhere up its inheritance chain, which
knows what kind of C structure is needed.

This scheme will fail if you somehow manage to extract
a built-in method out of one class and stuff it into
another. However there doesn't seem to be any obvious
way to do this (nothing like myClass.__dict__["foo"] in 
Python). So it seems to be safe.

Now, what happens if you assign to a new instance variable
in a method of your subclass of a built-in class? At first
sight it seems that this can't possibly work, because the
C structs of built-in types don't have any place to store
arbitrary instance variables.

When I tried it, however, to my surprise, it worked!
It turns out that there is a global table whose purpose
is to hold the values of these instance variables (in
Python terms it is a dictionary of dictionaries, indexed
by [object][variable_name]). Python might be able to
use a similar solution, although it might cause ref
counting problems.

As a final note, some built-in classes, such as Fixnum,
don't have any instantiation method, so although you can
subclass them, there's no point because you can never
create an instance of your subclass.

Others, however, such as Array (Ruby's version of ListType)
do have an instantiation method, and subclasses work
just the way you'd expect.

Hoping this has been enlightening,
Greg




More information about the Python-list mailing list