I am trying to better understand how modules expand and include each other.
Say I have module A :
module A def learned_from_A true end end A.instance_methods
I mix my tricks package in B :
module B extend A end B.learned_from_A
I naively try to give C all B :
module C extend B end C.learned_from_A
I think I wrapped it around this. When B extends A , copies of instance methods A are bound to B through the B singleton class:
B.singleton_methods # [:learned_from_A]
While: learn_from_A can be used for B , this is not one of the methods of instance B , so when C extends B ,: learn_from_A is not copied to C.
If B instead included A , copies of the methods of instance A would be included in the methods of native instance B.
module B include A end B.instance_methods
Then C can extend B , and all instances of B instance (including: learn_from_A) will be copied and attached to C.
module C extend B end C.singleton_methods
To do: learn_from_A can use either B or C , B can expand to include A.
module B include A extend A end B.instance_methods # [:learned_from_A] B.singleton_methods # [:learned_from_A] module C extend B end C.instance_methods # [] C.singleton_methods # [:learned_from_A]
More realistic, if I want methods A to be called on B , and for B to define another native method and be able to mix the entire repertoire in C , I cannot do this:
module B extend A include A def self.buzz true end end module C extend B end
B can only share its instance methods, and not with single methods. Therefore, to make a method as callable on B and shared by other objects, it must be defined as an instance method and extended into B itself:
module B extend A include A extend self def buzz true end end module C extend B end
There have been many trials and errors associated with this. Is this the exact way to see what happens?