Ruby Metaclass Confusion

Ruby metaclass confusion

how do this work

Easy: it doesn't. Not in Ruby, anyway.

Just like in most other languages, there are some core entities that are simply assumed to exist. They fall from the sky, materialize out of thin air, magically appear.

In Ruby, some of those magic things are:

  • Object doesn't have a superclass, but you cannot define a class with no superclass, the implicit direct superclass is always Object. [Note: there may be implementation-defined superclasses of Object, but eventually, there will be one which doesn't have a superclass.]
  • Object is an instance of Class, which is a subclass of Object (which means that indirectly Object is an instance of Object itself)
  • Class is a subclass of Module, which is an instance of Class
  • Class is an instance of Class

None of these things can be explained in Ruby.

BasicObject, Object, Module and Class all need to spring into existence at the same time because they have circular dependencies.

Just because this relationship cannot be expressed in Ruby code, doesn't mean the Ruby Language Specification can't say it has to be so. It's up to the implementor to figure out a way to do this. After all, the Ruby implementation has a level of access to the objects that you as a programmer don't have.

For example, the Ruby implementation could first create BasicObject, setting both its superclass pointer and its class pointer to null.

Then, it creates Object, setting its superclass pointer to BasicObject and its class pointer to null.

Next, it creates Module, setting its superclass pointer to Object and its class pointer to null.

Lastly, it creates Class, setting its superclass pointer to Module and its class pointer to null.

Now, we can overwrite BasicObject's, Object's, Module's, and Class's class pointer to point to Class, and we're done.

This is easy to do from outside the system, it just looks weird from the inside.

Once they do exist, however, it is perfectly possible to implement most of their behavior in plain Ruby. You only need very barebones versions of those classes, thanks to Ruby's open classes, you can add any missing functionality at a later time.

In your example, the class Class is not creating a new class named Class, it is reopening the existing class Class, which was given to us by the runtime environment.

So, it is perfectly possible to explain the default behavior of Class#new in plain Ruby:

class Class
def new(*args, &block)
obj = allocate # another magic thing that cannot be explained in Ruby
obj.initialize(*args, &block)
return obj
end
end

[Note: actually, initialize is private, so you need to use obj.send(:initialize, *args, &block) to circumvent the access restriction.]

BTW: Class#allocate is another one of those magic things. It allocates a new empty object in Ruby's object space, which is something that cannot be done in Ruby. So, Class#allocate is something that has to be provided by the runtime system as well.

The Class/Object Paradox confusion

You can see the problem in this diagram:

Ruby Method Lookup Flow

(source: phrogz.net)

All object instances inherit from Object. All classes are objects, and Class is a class, therefore Class is an object. However, object instances inherit from their class, and Object is an instance of the Class class, therefore Object itself gets methods from Class.

As you can see in the diagram, however, there isn't a circular lookup loop, because there are two different inheritance 'parts' to every class: the instance methods and the 'class' methods. In the end, the lookup path is sane.

N.B.: This diagram reflects Ruby 1.8, and thus does not include the core BasicObject class introduced in Ruby 1.9.

a confusing case in Ruby MetaProgramming

In addition to all other comments :

[from the Pickaxe] The method Object#instance_eval lets you set self to be some arbitrary object, evaluates the code in a block with [self], and then resets self.

And Module#define_method : Defines an instance method in the receiver [self, which must be a (anonymous) Class or Module].

singleton_class_of_object_a = aa = class << a; self; end
aa.instance_eval { def foo3; puts "foo3 from singleton class of a, self=#{self}"; end }
aa.foo3 # => foo3 from singleton class of a, self=#<Class:#<A:0x007fc2e4049e68>>
aa.instance_eval do
puts "about to define_method :bar3 in self=#{self}"
define_method :bar3 do; puts "bar3 from singleton class of a, self=#{self}"; end
end # => about to define_method :bar3 in self=#<Class:#<A:0x007fc2e4049e68>>
a.bar3 # => bar3 from singleton class of a, self=#<A:0x007fc2e4049e68>

define_method :bar3 is executed in the context of singleton_class_of_object_a (an anonymous class, see below), thus defines an instance method of that class, hence bar3 becomes a singleton method of a. As already said in my previous answer, it is equivalent to defining directly on the object :

def a.bar4; puts 'bar4 from singleton class of a' end
a.bar4 # => bar4 from singleton class of a

p a.singleton_methods.sort # => [:bar3, :bar4, :foo2]
p a.methods(false).sort # => [:bar3, :bar4, :foo2]



After a = A.new, the field class of instance a points to class A.

With class << a or def a.bar4, Ruby creates an anonymous class, the field class of instance a now points to this anonymous class, and from there to A.

Methods defined in this context with def or define_method go into the methods table of the anonymous class.

why are metaclasses created in ruby?

Just to be super duper clear.

Here is a quick ruby script that explains the question:

#!/usr/bin/env ruby
puts ObjectSpace.count_objects[:T_CLASS] #>> 471
class X
def self.foo
end
def bar
end
end
puts ObjectSpace.count_objects[:T_CLASS] #>> 473

This is what the OP meant by "ObjectSpace.count_objects[:T_CLASS] increments the count by 2." Let's call the extra class the singleton class of X, because that appears to be what Ruby calls it internally.

irb> X
=> X
irb> X.singleton_class
=> <Class: X>

Notice that the #foo method is an instance method of X.singleton_class, not X.

irb> X.instance_methods(false)
=> [:baz]
irb> X.singleton_class.instance_methods(false)
=> [:foo]

So why is :foo stored in X.singleton_class instead of X? Isn't there only ever going to be one X?

I believe the main reason is for consistency. Consider the following, simpler scenario concerning plain instance objects.

car = Car.new
def car.go_forth_and_conquer
end

As @mikej explained superbly, this new method is stored in car's singleton class.

irb> car.singleton_class.instance_methods(false)
=> [:go_forth_and_conquer]

Classes are Objects

Now, classes are objects too. Each class is an instance of Class. Thus, when a class (say, X) is defined, ruby is really creating an instance of Class, and then adding methods to the instance (similar to what we did to car above.) For example, here is an alternative way to create a new class

Car = Class.new do
def go_forth_and_conquer
puts "vroom"
end
end
Car.new.go_forth_and_conquer

Therefore, it is much easier to just reuse the code and do it the same way (i.e. keep foo in X.singleton_class.) This probably requires less effort and will lead to fewer surprises, so no one will ever need to write code to handle Class instances differently from other instances.

Probably Doesn't Matter

You might be thinking that if Ruby did not have singleton classes for instances of Class, there could be some memory savings. However, it sounds to me that where bar is actually stored is an implementation detail that we probably shouldn't count on. Rubinius, MRI, and JRuby could all store methods and instances differently, as long as the behavior is consistent. For all we know, there could be a reasonable implementation of Ruby that doesn't eagerly create singleton classes for class objects, for the exact same reasons you outlined, as long as the overall behavior conforms to the ruby spec. (E.g. an actual singleton class doesn't exist until the #singleton_class method is first invoked.)

ruby Metaprogramming and keyword self confusing

The questions you are asking here is really about the basics of how classes, methods, and objects work within Ruby.

What you have going on is really just the difference between class methods and instance methods.

An instance method means in the most basic sense that the method can only be called from the level of an instantiated object.

This is what you see with your syntax here.

class A
def hi
"hi"
end
end

In this case the method hi is an instance method of class A and so we must instantiate an object to call it. To avoid confusion between casing a vs A I will use foo instead of a

foo = A.new
foo.hi

Now we have just created an instance foo of A and as such we can call the method hi on foo.

Next we have class methods, or methods that can be called at the level of the class. In Ruby there are multiple syntaxes to achieve this, with all of the following being semantically equivalent.

class A
self.hello
"hello"
end
end

class A
A.hello
"hello"
end
end

class A
class << self
def hello
"hello"
end
end
end

Now one of the nice things about the last version that uses class << self is that we can define multiple methods in that section. I go back and forth between the last two methods above depending on what I'm doing and almost never use the first version, but this is just personal preference.

Now, up to this point, everything I have said is pretty much Ruby's implementation of standard OO class/method definition and similar concepts are going to be found in any other OO language you have used C++, Java, C#, etc...

The last piece where you were confused is where Ruby steps into the idea of metaclasses or as they are typically referred to in Ruby as "eigenclasses".

What this basically means is that there is a class that you do not define that exists between the class and the instance. This is a bit confusing; read here for more clarity (http://en.wikipedia.org/wiki/Metaclass).

But what this allows us to do is define methods directly on an instance so the methods exist only on that instance and not on other instances of the class.

This is where the syntax below comes in.

class << foo
def hi
"hi from foo"
end
end

Now the method hi has been overridden only for the instance foo. This can also be used to define completely new methods that only exist on the instance. For example

class << foo
def bar
"bar"
end
end

Now if we instantiate a new instance of A

b = A.new

The method bar does not exist on b; it only exists on the instance foo.

Ruby metaclass madness

Defining a singleton method dynamically is simple when you use instance_eval:

Example.instance_eval{ def square(n); n*n; end }
Example.square(2) #=> 4
# you can pass instance_eval a string as well.
Example.instance_eval "def multiply(x,y); x*y; end"
Example.multiply(3,9) #=> 27

As for the difference above, you are confusing 2 things:

The meta class defined by you, is what called in Ruby community as singelton class or eigen class. That singleton class is the class that you can add class(singleton) methods to.

As for the class instance you are trying to define using the class_instance method, is nothing but the class itself, to prove it, just try adding an instance method to the class Example and check if the class_instance method defined by you returns the class Example itself by checking the existence of that method:

class Example
def self.meta; (class << self; self; end); end
def self.class_instance; self; end
def hey; puts hey; end
end

Example.class_instance.instance_methods(false) #=> ['hey']

Anyway to sum it for you, when you want to add class methods, just add them to that meta class. As for the class_instance method is useless, just remove it.

Anyway I suggest you read this post to grasp some concepts of Ruby reflection system.

UPDATE

I suggest you read this nice post: Fun with Ruby's instance_eval and class_eval,
Unfortunately class_eval and instance_eval are confusing because they somehow work against their naming!

Use ClassName.instance_eval to define class methods.

Use ClassName.class_eval to define instance methods.

Now answering your assumptions:

If I have an instance method which
calls self.instance_eval and defines a
method, it will only affect the
particular instance of that class.

yes:

class Foo
def assumption1()
self.instance_eval("def test_assumption_1; puts 'works'; end")
end
end

f1 = Foo.new
f1.assumption1
f1.methods(false) #=> ["test_assumption_1"]
f2 = Foo.new.methods(false) #=> []

If I have an instance method which
calls self.class.instance_eval (which
would be the same as calling
class_eval) and defines a method it
will affect all instances of that
particular class resulting in a new
instance method.

no instance_eval in that context will define singleton methods(not instance ones) on the class itself:

class Foo
def assumption2()
self.class.instance_eval("def test_assumption_2; puts 'works'; end")
end
end

f3 = Foo.new
f3.assumption2
f3.methods(false) #=> []
Foo.singleton_methods(false) #=> ["test_assumption_2"]

For that to work replace instance_eval with class_eval above.

If I have a class method which calls
instance_eval and defines a method it
will result in a new instance method
for all instances.

Nope:

class Foo
instance_eval do
def assumption3()
puts 'works'
end
end
end

Foo.instance_methods(false) #=> []

Foo.singleton_methods(false) #=> ["assumption_3"]

That will make singleton methods, not instance methods. For that to work replace instance_eval with class_eval above.

If I have a class method which calls
instance_eval on the meta/eigen class
and defines a method it will result in
a class method.

well no, that will make so sophisticated stuff, as it will add singleton method to the singleton class, I don't think that will have any practical use.

In Ruby, are the terms metaclass, eigenclass, and singleton class completely synonymous and fungible?

tl;dr: Yes.

In the past, nobody knew what to call them, so everybody called them something else. Here is just a small sample of the names different authors have used or proposed over time:

  • singleton class
  • eigenclass
  • metaclass
  • ghost class
  • own class
  • virtual class
  • shadow class
  • myclass
  • selfclass
  • overclass
  • underclass
  • anchorclass
  • embedded class
  • intrinsic class
  • innate class
  • nameless class
  • unit class
  • atom class
  • singular class
  • singularity
  • bongo class
  • inner class

Originally, matz didn't want to choose a name, rather he wanted the community to settle on one. Unfortunately, it didn't. When matz and David Flanagan wrote The Ruby Programming Language, they had to choose, and they chose eigenclass (but singleton method). Eigenclass was also used in the first drafts for the ISO Ruby Language Specification (but mainly because it was very easy to run a search&replace on that name once an "official" one had been found).

However, in the later drafts and the final version of the ISO Ruby Language Specification, singleton class is used. That name was also chosen, when the Object#singleton_class accessor method was finally formally introduced in Ruby 1.9.2 and Module#singleton_class? was introduced in Ruby 2.1.

Metaclass was the term used by _why the lucky stiff in Why's (Poignant) Guide to Ruby (and other writings and libraries), which was highly influential on a whole generation of non-Japanese-speaking Ruby developers, and for a long time the best introduction to Ruby metaprogramming (and the only English one).

Nowadays, the terms singleton class and eigenclass seem to predominantly used (with singleton class taking over, thanks to the method names in the core library), with the occasional mention of metaclass.

Personally, I never liked metaclass, because it actually already has a different meaning: the metaclass is the class of a class. In Ruby, classes have two classes that define their behavior: their singleton class and the Class class, either one of which could be considered their metaclass. (Although neither of those classes can do what metaclasses in other languages can do, e.g. change the rules the method lookup or inheritance.)

Virtual class is even more problematic, because not only does it have a different meaning in programming in general (a nested class that can be overridden in a subclass, as in e.g. Beta or Newspeak, and proposed but abandoned for Scala), it even already has a third different meaning within the Ruby community: virtual class is the name given inside the MRI and YARV source code to singleton classes and include classes.

Inner class also already has a meaning as synonym to nested class (a class which is a member of an outer class, just like a method).

Personally, I always liked eigenclass, in symmetry to already established technical terms such as eigenvalue, eigenvector, eigenspace, eigenfunction, eigenface, eigenwave, eigenplane, eigenstate, eigenproblem etc. However, I have now adopted the term singleton class, simply because it's easier to talk about the singleton_class method as returning the singleton class.



Related Topics



Leave a reply



Submit