Skip to content

Instantly share code, notes, and snippets.

@cowboyd
Created January 19, 2012 21:28
Show Gist options
  • Save cowboyd/1642793 to your computer and use it in GitHub Desktop.
Save cowboyd/1642793 to your computer and use it in GitHub Desktop.
Ruby classes inherit methods on singleton classes
# I never knew that singleton methods defined on a class are callable via subclasses
# Apparently when you create a subclass, that subclass's singleton class has
# its superclass's singleton class as an ancestor.
class Foo
@blip = 'foo'
def self.foo; @blip;end
end
class Bar < Foo
@blip = 'bar'
end
puts Foo.foo #=> foo
puts Bar.foo #=> bar
puts Bar.singleton_methods #=> [:foo]
puts Bar.singleton_class < Foo.singleton_class #=> true
# My prior understanding would have had Bar's ancestor graph looking like
# [Bar.singleton_class, Class, Module, Object, ...]
#
# But instead it is something more along the lines of
# [Bar.singleton_class, Foo.singleton_class, Class, Module, Object,...]
#
# Even though calling ancestors() on both of them yields
# [Class, Module, Object, ...]
#
# This is pretty handly, but will require me to recalibrate my understanding of Ruby's insides.
# Is there a way to view the actual full ancestor list for any given class/module?
@floehopper
Copy link

I played around with something to give me the list of receivers for any Ruby object in my introspection gem. If you load the "introspection/receivers" file you get a method #receivers on any object which gives you the whole receiver chain. I did it a while ago, so it may only work in Ruby v1.8.7.

@jacobdam
Copy link

I've noticed that singleton methods defined on a class are callable via subclasses. I wondered why it is possible. Thanks for your code. 👍

@McTano
Copy link

McTano commented Aug 30, 2016

Good post, thanks. I've been trying to wrap my head around all this eigenclass stuff.
I see this post is five years old, so this may not have been available at the time, but at least in recent versions of Ruby, calling ancestors on the singleton class does show the other singleton classes.
class A; end => nil
class B < A; end => nil
B.singleton_class => #<Class:B>
B.singleton_class.ancestors => [#<Class:B>, #<Class:A>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, JSON::Ext::Generator::GeneratorMethods::Object, Kernel, BasicObject]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment