这是一个外部类,其class方法已被覆盖。
class Foo
def class
"fooo"
end
end
class Boo < Foo
end
class Moo < Foo
end
Run Code Online (Sandbox Code Playgroud)
现在,我有一个子类的实例。是否可以找出它属于哪个类?
foo.class # currently returns 'fooo', I want get Boo or Moo.
Run Code Online (Sandbox Code Playgroud)
您可以用来从安全的地方(例如)instance_method获取class方法,将未绑定的方法绑定到您的实例,然后调用它。例如:ObjectUnboundMethod
class_method = Object.instance_method(:class)
# #<UnboundMethod: Object(Kernel)#class>
class_method.bind(Boo.new).call
# Boo
class_method.bind(Moo.new).call
# Moo
class_method.bind(Foo.new).call
# Foo
Run Code Online (Sandbox Code Playgroud)
当然,如果您也替换了Object#class(或Kernel#class),那么所有的赌注都消失了,您将面临一个全新的痛苦与困惑世界。
我更喜欢@Stefan和@muistooshort的解决方案,但这是替代方案。
class Foo
def class
"foo"
end
end
class Boo < Foo
end
class Who < Boo
def class
"who"
end
end
Run Code Online (Sandbox Code Playgroud)
boo = Boo.new
boo.method(:class).super_method.call
#=> Boo
who = Who.new
who.method(:class).super_method.call
#=> "foo"
who.method(:class).super_method.super_method.call
#=> Who
Run Code Online (Sandbox Code Playgroud)
更普遍:
def my_class(obj)
m = obj.method(:class)
until m.owner == Kernel do
m = m.super_method
end
m.call
end
my_class(boo)
#=> Boo
my_class(who)
#=> Who
Run Code Online (Sandbox Code Playgroud)
对象的类也恰好是superclass其的类singleton_class:
Boo.new.singleton_class.superclass
#=> Boo
Moo.new.singleton_class.superclass
#=> Moo
Foo.new.singleton_class.superclass
#=> Boo
Run Code Online (Sandbox Code Playgroud)