代码之家  ›  专栏  ›  技术社区  ›  Alexander Presber

通过多个include重写实例方法

  •  0
  • Alexander Presber  · 技术社区  · 7 月前

    以ruby 3.3.0中的以下代码为例:

    module A
      def print
        puts "A"
      end
    end
    
    module B
      def print
        puts "B"
      end
    end
    
    class C
    end
    
    c_instance = C.new
    
    C.send(:include, A)
    c_instance.print
    
    C.send(:include, B)
    c_instance.print
    
    C.send(:include, A)
    c_instance.print
    

    我希望它能打印出来:

    A
    B
    A
    

    但它打印出来了

    A
    B
    B
    

    为什么?

    2 回复  |  直到 7 月前
        1
  •  2
  •   GProst    7 月前

    Ruby忽略第二个调用。 来自Ruby docs :

    Ruby的默认实现是将该模块的常量、方法和模块变量添加到mod中,如果该模块尚未添加到mod或其祖先之一中。另请参阅模块#include

    这是引用自 append_features 方法描述,用于 include 方法

        2
  •  1
  •   kevinluo201    7 月前

    它可能无法直接回答您的问题,但您可以使用 ancestors 以检查最终的继承链。

    C.ancestors
    # => [C, B, A, Object, Kernel, BasicObject]
    

    有许多方法可以在Ruby中进行动态元编程。这一次你被 :include ,下次你可能会被 :prepend 甚至是其他类型的神秘遗产。你甚至可以使用

    c_instance.method(:print).source_location
    

    那个方法里面到底是什么