Reputation: 403
I was watching the first ruby metaprogramming screencast by prag dave. At some point he said that ruby introduce 'ghost classes' when you add a method to an instance variable. i.
animal = "cat"
def animal.speak
puts "hola"
end
animal.speak # => hola
animal.class # => String
dog = "dog"
dog.speak # Undefined method `speak' for "dog":String
String.send :speak # NoMethodError: undefined method `speak' for String:Class
animal.send :speak # hola
Where is really the speak method store? If it is an invisible proxy class, How can we access to that proxy class?
Upvotes: 2
Views: 1089
Reputation: 24010
Some ppl call it "Singleton Class"
singleton_class = class << animal; self; end
And actually this singleton class is the host for class methods at any class, check this example, first by defining class Foo with class methods 'hi' and 'bye':
class Foo
def self.hi ; p "hi" ; end
def self.bye ; p "bye" ; end
end
Foo.singleton_methods #=> ["hi","bye"]
Now let's define a method that returns back the singleton class for us:
class Object
def singleton_class
class << self
self
end
end
end
Now try this :
Foo.singleton_methods #=> ["bye", "hi"]
Foo.singleton_class.instance_methods(false) #=> ["bye", "hi"]
Upvotes: 1
Reputation: 23901
The method speak
is stored in a metaclass (also known as an eigenclass), what you call an "invisible proxy class". In Ruby, instance variables have no place to store methods. They can only store instance variables and their class. So when you add a method to an instance, a metaclass is created and inserted into its class chain. For a better understanding of the internals, I recommend this article from Klank Boom Klang.
In order to get at the meta class, you can do the following:
animal = "cat"
def animal.speak
puts "hola"
end
animal.speak # => hola
animal.class # => String
metaclass = class << animal; self; end
metaclass.inspect # => #<Class:#<String:0x2c9c460>>
metaclass.instance_methods.index 'speak' # => 102
metaclass.class # => Class
Upvotes: 4