gpt4 book ai didi

对象的 Ruby 方法查找路径

转载 作者:数据小太阳 更新时间:2023-10-29 07:09:47 27 4
gpt4 key购买 nike

是否有内置的 Ruby 方法或众所周知的库可以返回对象的整个方法查找链? Ruby 查看一系列令人困惑的类(如 this question 中所讨论)以查找与消息对应的实例方法,如果没有类响应消息,则调用接收方的 method_missing

我将以下代码放在一起,但我确信它遗漏了某些情况或者它是否 100% 正确。请指出任何缺陷并指导我找到一些更好的代码(如果存在)。

def method_lookup_chain(obj, result = [obj.singleton_class])
if obj.instance_of? Class
return add_modules(result) if result.last == BasicObject.singleton_class
r = result.last.superclass
method_lookup_chain(obj, result << r)
else
return result + obj.class.ancestors
end
end

def add_modules(klasses)
r = []
klasses.each_with_index do |k, i|
r << k
next if k == klasses.last
r << (k.included_modules - klasses[i+1].included_modules)
end
r.flatten
end

# EXAMPLES

module ClassMethods; end
module MoreClassMethods; end
class A
extend ClassMethods
extend MoreClassMethods
end
p method_lookup_chain(A) # => [#<Class:A>, MoreClassMethods, ClassMethods, #<Class:Object>, #<Class:BasicObject>]

module InstanceMethods; end
class Object
include InstanceMethods
end
module X; end
module Y; end
class Dog
include X
include Y
end
d = Dog.new
p method_lookup_chain(d) # => [#<Class:#<Dog:0x007fcf7d80dd20>>, Dog, Y, X, Object, InstanceMethods, Kernel, BasicObject]

最佳答案

另一篇文章使它看起来令人困惑,但实际上并非如此。如果您对这些东西感兴趣,您应该阅读“Metaprogramming Ruby”。在那之前,基本规则是 one step to the right and up :

          Object (superclass)
^
|
Parent class A(superclass)
^
|
Parent class B(superclass)
^
|
obj -> object's class

2) 在对象和对象的类之间插入单例类:

          Object
^
|
Parent class A(superclass)
^
|
Parent class B(superclass)
^
|
object's class(superclass)
^
|
obj -> obj's singleton_class

3) 包含的模块直接插入到执行包含的类之上:

          Object
^
|
Parent class A
^
|
Module included by Parent Class B
^
|
Parent class B
^
|
object's class
^
|
obj -> obj's singleton_class

编辑:

Please point out any flaws

p method_lookup_chain(Class)

--output:--
[#<Class:Class>, #<Class:Module>, #<Class:Object>, #<Class:BasicObject>]

但是……

class Object
def greet
puts "Hi from an Object instance method"
end
end

Class.greet

--output:--
Hi from an Object instance method

还有..

class Class
def greet
puts "Hi from a Class instance method"
end
end

Class.greet

--output:--
Hi from a Class instance method

在类上调用的方法的查找路径实际上继续经过 BasicObject 的单例类(#<Class:BasicObject>):

class BasicObject
class <<self
puts superclass
end
end

--output:--
Class

在 Class 上调用的方法的完整查找路径如下所示:

                  Basic Object                 
^
|
Object
^
|
Module
^
|
Class
^
|
BasicObject BasicObject's singleton class
| ^
| |
Object Object's singleton class
| ^
| |
Module Module's singleton class
| ^
| |
Class ---> Class's singleton class

查找从 Class 的单例类开始,然后在右侧的层次结构中向上查找。 《Metaprogramming Ruby》声称对所有对象都有一个统一的查找理论,但是对类调用方法的查找并不符合3)中的图表。

你这里有同样的问题:

class A 
end

class B < A
end

p method_lookup_chain(B)

--output:--
[#<Class:B>, #<Class:A>, #<Class:Object>, #<Class:BasicObject>]

应该是这样的:

                  Basic Object                 
^
|
Object
^
|
Module
^
|
Class
^
|
BasicObject BasicObject's singleton class
| ^
| |
Object Object's singleton class
| ^
| |
A A's singleton class
| ^
| |
B.greet --> B's singleton class

您需要记住一件事:在类上调用的任何方法的查找路径都必须在某处包含 Class,因为所有类都继承自 Class。

关于对象的 Ruby 方法查找路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23848667/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com