问题
I am writing a module with method foo
, which calls a class method bar
on the receiver's class. My current approach is to use self.class.bar
, which works fine unless the class method is defined in an instance class instead of a "real" one:
module M
def foo
self.class.bar
end
end
obj = Object.new
class << obj
include M
def self.bar
42
end
end
obj.foo # => NoMethodError: undefined method `bar' for Object:Class
This makes sense because obj.class
does not return singleton classes. I could use obj.singleton_class
instead, and everything would run smoothly:
module M
def foo
self.singleton_class.bar
end
end
obj = Object.new
class << obj
include M
def self.bar
42
end
end
obj.foo # => 42
only if the method is defined on a singleton class for the same reason as above. Worse still, it creates a new singleton class for every receiver, something I want to avoid as these might be a fair amount of objects. So instead, I want some way to retrieve an object's singleton class if and only if it is already defined, i.e. something of the type obj.has_singleton_class ? obj.singleton_class : obj.class
. I couldn't find any way to perform this check though.
回答1:
Every object always has a singleton class in Ruby. The specific implementation you use (MRI, YARV, Rubinius, JRuby, IronRuby, MacRuby, MagLev, MRuby, etc.) may or may not optimize memory usage by not allocating memory for a singleton class that isn't used, but that's a private internal implementation detail, an invisible transparent compiler optimization. Whenever you go looking for a singleton class, it'll be there.
Well, actually, that's not quite true. Immediate values, i.e. Integer
s, Symbol
s and Float
s cannot have singleton classes.
So, those three will never have a singleton class, all others always have a singleton class.
来源:https://stackoverflow.com/questions/16501353/check-if-an-object-has-a-singleton-class