Ruby method lookup path for an object

后端 未结 1 1941
天命终不由人
天命终不由人 2020-11-30 07:19

Is there a built-in Ruby method or a well-known library that returns the entire method lookup chain for an object? Ruby looks through a confusing sequence of classes (as di

相关标签:
1条回答
  • 2020-11-30 07:35

    That other post makes it seem confusing, but it really isn't. If you are interested in such things, you should read "Metaprogramming Ruby". Until then, the basic rule is one step to the right and up:

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

    2) Singleton classes are inserted between the obj and the object's class:

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

    3) Included modules are inserted immediately above the class that does the including:

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

    Edit:

    Please point out any flaws

    p method_lookup_chain(Class)
    
    --output:--
    [#<Class:Class>, #<Class:Module>, #<Class:Object>, #<Class:BasicObject>]
    

    But...

    class Object
      def greet
        puts "Hi from an Object instance method"
      end
    end
    
    Class.greet
    
    --output:--
    Hi from an Object instance method
    

    And..

    class Class
      def greet
        puts "Hi from a Class instance method"
      end
    end
    
    Class.greet
    
    --output:--
    Hi from a Class instance method
    

    The lookup path for a method called on a class actually continues past BasicObject's singleton class(#<Class:BasicObject>):

    class BasicObject
      class <<self
        puts superclass
      end
    end
    
    --output:--
    Class
    

    The full lookup path for a method called on Class looks like this:

                      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
    

    The lookup starts in Class's singleton class and then goes up the hierarchy on the right. "Metaprogramming Ruby" claims there is a unified lookup theory for all objects, but the lookup for methods called on a class does not fit the diagram in 3).

    You have the same problem here:

    class A 
    end
    
    class B < A
    end
    
    p method_lookup_chain(B)
    
    --output:--
    [#<Class:B>, #<Class:A>, #<Class:Object>, #<Class:BasicObject>]
    

    It should be this:

                      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
    

    One thing you need to keep in mind: the lookup path of any method called on a class has to include Class somewhere because ALL classes inherit from Class.

    0 讨论(0)
提交回复
热议问题