Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link

@floehopper floehopper commented Jan 19, 2012

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

This comment has been minimized.

Copy link

@jacobdam jacobdam commented Mar 12, 2015

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

This comment has been minimized.

Copy link

@McTano 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