rubymetaprogrammingeigenclass

Ruby eigenclass (sigleton class) created? For which?


Got confused on Ruby meta-programming.

So from the tutorial I learnt the following:

cat = "kitty"
cat.upcase  # "KITTY"
cat.poop    # undefined 'poop'

def cat.poop
  puts 'pooooooo...'
end

cat.upcase  # "KITTY"
cat.poop    # "pooooooo..."

So this means poop method is already for the cat object, which is of class String. From the famous textbook "Programming Ruby", by defining cat.poop, what actually happens is Ruby created an anonymous class, aka singleton or eigenclass, that is now the class of the cat object, then the original String class becomes the superclass of the newly created eigenclass.

Then this confused me. See the following code:

cat.poop    # "pooooooo...", it works, for sure
cat.class   # "String" | but this is NOT some other class

cat = "kate"
cat.poop    # poop not defined

3 questions:

  1. it does not look like there is any new class was ever created when defining the poop method. Or maybe the it was created, but the "#class" method automatically redirected the call to the superclass' #class? Which is correct? How do we check?

  2. if we define another method, say cat.run, then will another eigenclass created or not? What will be the class hierarchy then?

  3. if cat is redefined to "kate", the poop is not found. Why? Shouldn't the poop be available to cat?

Thanks!


Solution

    1. Look at cat.singleton_class and cat.singleton_methods.
    2. No. Define a couple singleton methods on cat and then look at cat.singleton_class.instance_methods and you'll see them both there. You can get a hint about the hierarchy with cat.singleton_class.ancestors.
    3. You've defined cat to be some entirely new object now. Why would it have the same methods? If you say cat = "string" then you can call cat.upcase, but if you later reassign cat = 5, of course you can't still call cat.upcase.