virtual metaclasses explanation

A

angel.of.north

I am getting a bit weighed down at this moment by looking under the
bonnet a bit too much, but in figure 24.2 in Dave Thomas Pragmatic
Programming,
classes and objects is is unclear how the metaclass acquires its
additional method as strings.
Dave Rhomas says that the metaclass will inherit all it methods from
its corresponding proper class.

1. Do all inheritance chains and all objects have a homologue
metaclass at all times, which are behind the scenes?
2. Do a chain of metaclasses spontaneously appear at the moment
when a class is used as a receiver : so to be used to call a method
inside of a parentclass?
3. How can a metaclass contain more methods than its corresponding
class has. Can you give an example of the code in the next addition?
4. Which is searched first in the inheritance chain. methods in
the proper parents, or methods in the meta parents?
5. If a method is found is the search stopped even though another
method with the same name might exist in a parallel chain?

I have made some written notes as I went along which might interest
you. It is useful to know how the reader is progressing.

def ClassA
def initialize
#some code
end
end

def ClassB
def ClassA.methodX
#code
end
def ClassB.methodY
#code
end
end



both work.
Is this a good idea to define a class method within a different
class? is this the point of OO or is it bad programming style?

Andy Hunt says

It depends. In general, that's probably bad style as you're likely
violating the encapsulation of ClassA.

Regards,

/\ndy

\newpage

class ClassA
def initialize
puts "something classA"
end
end

class ClassC
def initialize
puts "someting classC"
end
def methodY
puts "beach balls"
end
end



class ClassB < ClassC
def methodY
super
puts "something ClassB.methodY"
end
end

test = ClassA.new
stuart = ClassB.new
puts stuart.methodY




stuart = ClassB.methodY

or

stuart = ClassB.new
stuart.methodY

stuart is an object which is initialized of the class method as
ClassB.new which is mostly defined as an ordinary method called
initialize inside of and at the beginnning of the class as ClassB

Sometimes the object as stuart will be referred by as the receiver if
a method within the class by which the object as stuart is defined, is
called after the object name as stuart. i.e stuart.methodY. Stuart is
reffered by as the receiver so to indicate that the class of the
object as stuart, which in this case is the class as ClassB, contains
a method which the object as stuart may access ; i.e stuart.methodY.

The object as Stuart is related by the class as ClassB. The object as
stuart is of the class as ClassB. The word as related means the same
as the word as linked within this context.

Each class may be part of an inheritance chain.

But the class as classB may also be considered an object. Therefore
the class as classB itself may also be used as a receiver. e.g.

ClassB.methodZ

where the method as Z is defined within the class as ClassC : which is
the parentclass of ClassB.
or
where the method as Z is defined within the class as ClassB' : which
is a virtual class of ClassB.
Because ClassB' is the virtual class of ClassB and Class B is also the
subclass of ClassC, another virtual class as ClassC is established to
be the virtual parentclass of the virual class as ClassB'. None of
these virtual classes are supposed to be immediately visible. The
virtual class as ClassB' will contain all the methods of ClassB and
this pattern is repeated through the parallel inheritance chain.







which is derived from
comp.lang.ruby August 9 2005


ANSWER

As you guessed, the reasons are different: typically you use "class
<<something...end" if you have to define several methods or if you
need a
class context for things to work (for example "alias").

These are equivalent:

class Foo
class <<self
def m1() "foo" end
end


class <<Foo
def m2() "foo" end
end


def self.m3() "foo" end
def Foo.m4() "foo" end
end


class <<Foo
def m5() "foo" end
end


def Foo.m6() "foo" end


x = Foo
def x.m7() "foo" end


class <<x
def m8() "foo" end
end


Now you have methods m1 to m8 as instance methods of Foo. You can do
Foo.m1(), Foo.m2 etc.

More technically, with class <<something ... end you make definition
for
the so called "singleton class" the class instance responsible for the
single instance at hand (which happens to be a class object in this
case;
but you can repeat the example above with any object instead of Foo).
You
cannot create instances from this class:


irb(main):001:0> class Foo
irb(main):002:1> p new
irb(main):003:1> end
#<Foo:0x10192d58>
=> nil
irb(main):004:0> class <<Foo
irb(main):005:1> p new
irb(main):006:1> end
TypeError: can't create instance of virtual class
from (irb):5:in `new'
from (irb):5



-- No virus found in this incoming message. Checked by AVG Free
Edition. Version: 7.5.467 / Virus Database: 269.7.7/816 - Release
Date: 23/05/2007 15:59
 
R

Rick DeNatale

I am getting a bit weighed down at this moment by looking under the
bonnet a bit too much, but in figure 24.2 in Dave Thomas Pragmatic
Programming,
classes and objects is is unclear how the metaclass acquires its
additional method as strings.
Dave Rhomas says that the metaclass will inherit all it methods from
its corresponding proper class.

I don't have the time to digest your long thread which followed, but
I'll try to address these questions.
1. Do all inheritance chains and all objects have a homologue
metaclass at all times, which are behind the scenes?

In ruby metaclasses are singleton classes of classes. Just as a class
holds the table used to find the methods of its instances, the
metaclass holds the table used to find methods for its sole instance
i.e. the class.

The singleton class which serves as the metaclass of a class is
created when the class is created. This is done internally by the
Ruby interpreter.

While object's don't have metaclasses they can have singleton classes,
which are created when needed, e.g. when you do something like

a = "abc"
b = "def"

def a.method;...;end # singleton class for the object referenced by
a is created now
class <<b #singleton class for the object referenced by b is created now
...
end
2. Do a chain of metaclasses spontaneously appear at the moment
when a class is used as a receiver : so to be used to call a method
inside of a parentclass?

No, as I just said, metaclasses are created along with their
corresponding class. The metaclass' superclass is set to the
metaclass of the classes superclass. This is one difference between
singleton classes of objects and singleton classes used as
metaclasses. The later can have subclasses, while the former cannot.

Normal object singleton classes have their internal superclass set to
the original class of the object.

Note that I'm using superclass and class here to describe the internal
relationship. Ruby's class and superclass methods don't always give a
true picture when singleton/metaclasses are involved. I personally
think of the class-like objects linked together with the superclass
field as a behavior chain since it's used to implement the behaviour
of one or more objects.
3. How can a metaclass contain more methods than its corresponding
class has. Can you give an example of the code in the next addition?

The number of methods in the class and the number of methods in the
metaclass is completely independent, for example, look at the
following and compare it to what I said in reponse to question #1

class MyClass

def initialize # This defines the initialize method in MyClass which
# Like all such methods are available to INSTANCEs
# of the class, and its subclasses
#
end

def method1 # another instance method
end

def MyClass.class_method # This defines a class method in the
# singleton class of MyClass (i.e. the metaclass)
# which is available to instances of the
metaclass and
# its subclasses
end

def self.class_method_2 # This adds another class method, it's
# Just a different syntax for the last
form of definition
# since within the scope of a class
definition, self is
# bound to that class
end

class << self # or equivalently class << MyClass
# Now we are in an inner scope, that of MyClass' metaclass
def class_method_3 # So this also becomes a class method
# of MyClass
end
end

So MyClass has two instance methods (plus what it inherits from
Object) and three class methods (plus what the metaclass inherits from
Object's metaclass.

As a related note, when a class includes a Module, another kind of
virtual class is inserted between the class and it's superclass. This
virtual class (or I_Class) looks like a class but has a pointer to the
method table of the module instead of having its own table. This
lets modules appear in different behavior chains and lets those
including them see updates to the module when they are made. There
are some other fields of the module which are also copied, but I'm not
going to mention them here since they aren't relevant and might
confuse.
4. Which is searched first in the inheritance chain. methods in
the proper parents, or methods in the meta parents?

There's no cross over at all. When finding a method for an object,
Ruby gets the head of what I called the behavior chain. For a normal
object with no singleton class, this will be the class, For an object
with a singleton class this will be the singleton class. If the
method is found, then it's used, if not the next class-like thing in
the behavior chain is examined and so forth. The keyword super makes
the search start in the next link in the behavior chain after the one
in which the current method was found.

So if you're invoking a method on a normal object, no metaclasses will
be on the chain. If you are invoking a method on a class, then the
behavior chain will consist of metaclasses, except that the superclass
of Object's metaclass is Class. If you think about this hard enough it
makes sense, since the instance methods of Class are for use by
classes.

So if we have

class B
...
end

b = B.new
b.to_s

The search goes:

B -> Object -> (I_Class wrapper for Kernel)
the last is because Object includes Kernel

and
B.new
the search goes

(singleton of B) -> (singleton of Object) -> Class -> Module ->
Object -> (I_Class wrapper for Kernel)
5. If a method is found is the search stopped even though another
method with the same name might exist in a parallel chain?

As I just described, the parallel chain is irrelevant, it isn't
considered at all.

HTH
 
A

angel.of.north

Thankyou for replying at such length. I am sure that what you have
explained I will understand properly soon. I think that this post
deserves some web links.

David R
 

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

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top