As we can see, Class actually inherit from Module.
RUBY doesn’t allow multiple inheritances. To achieve that we can use the mixin facilities by importing the module.
MODULE
There are 3 ways to import a mixin facility to a classinclude,prepend, extend.Let see what difference between them.
1. include
is the most used and the simplest way of importing module code. When calling it in a class definition, Ruby will insert the module into the ancestry chain of the class, just after it.
module T1; end module T2; end module T3; endclass A include T1 include T2 end A.ancestors #=> [A, T2, T1, Object, Kernel, BasicObject]Object.class_eval do include T3 end A.ancestors #=> [A, T2, T1,Object, T3, Kernel, BasicObject]
Import instance methods, instance variables from module to the class. It means the class’s instances can have module methods (only instance methods, not class methods), instance variables.
class also can access module’s class_variable, but not class_instance_variable.
No import class methods
2. prepend
the same method as include but the module will be inserted to the beginning of the ancestry line
module T1 def t 'method t of module T1' end endmodule T2 def t 'method t of module T2' end endclass A prepend T1 include T2 def t 'method t of class A' end end A.ancestors #=> [T1,A, T2, Object, Kernel, BasicObject]A.new.t #=> it would print 'method t of module T1'. Because when call a method, ruby will seek it from the beginning of the chain. If the T1 doesn't have "t" method, it continues search on the next one on the right.
3. extend
When a class extends a module, only the module’s instance methods are imported to its singleton class, both module’s class methods and the variables aren’t imported.
With extend, the module would not be inserted into the class’s ancestry chain.
module T1 def method_1 'method 01' end endmodule T2 endclass A extend T1 include T2 end A.ancestors #=> [A, T2, Object, Kernel, BasicObject]A.singleton_methods => [:method_1]
4. callback and one-time import
Ruby support callback include, prepend, extend a module.
a module can only import one time to the ancestry chain.
module T def self.included(klass) p "callback when included module T from #{klass.name}" enddef self.prepended(klass) p "callback when prepended module T from #{klass.name}" enddef self.extended(klass) p "callback when extended module T from #{klass.name}" end endclass A include T prepend T extend T end#=> "callback when included module T from A" #=> "callback when prepended module T from A" #=> "callback when extended module T from A"a.ancestors #=> [A, T, Object, Kernel, BasicObject] class B < A include T # Because T already exist on the ancestry chain, then no action happen, but the callback still fire end #=> "callback when included module T from B"b.ancestors #=> [B, A, T, Object, Kernel, BasicObject]
Class
When class A inherits from class B, A inherits all methods and variables from B (both private, protected, public)
What difference between private, protected, public variable/method?
Constant Table and Nested Constant
As default, both class and modulehave their access to their internal constants that have been stored in constant table. We can check the accessible constant by the method constants
When calling a constant inside a nested, Ruby will look at the nesting constant of the scope
passion in finding solutions and research some things relate to technical and helpful in life. Also strongly interest in foods, travel, and gentle music :)