Ruby classes inherit methods on singleton classes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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? |
I've noticed that singleton methods defined on a class are callable via subclasses. I wondered why it is possible. Thanks for your code.
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
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.