Method calls in ruby are allObject. MethodSo how to find this method for the object?
First, you must understand the concept of the ancestor chain. The ancestor chain starts from a class to its parent class, and then to the parent class of the parent class... until the final starting point (the basicobject class in Ruby ). During this period, the path that we experienced was the ancestor chain.
1. Search for mixed modules and inheritance Methods
For an instance object, first check whether there are corresponding instance methods in the class it belongs to, and then check whether there are modules in the class. If so, check whether there are corresponding methods in the module, if no, find the parent class. First, let's look at the instance method of the parent class, then check whether there are modules in the parent class, and then look at the parent class of the parent class... until the end, the basicobject class and the kernel module.
If not, you can view the method_missing function, which is a built-in function. This function reports an error by default. Of course, you can rewrite this method to process unfound methods.
As follows:
1 module M 2 def method 3 puts "this is method in module M" 4 end 5 end 6 7 class C 8 include M 9 end10 11 class D < C;end12 13 D.new.method14 p D.ancestors
The output is
This is method in module M
[D, C, M, object, kernel, basicobject]
In this example, the object d. New of class D needs to find the method: first find the instance method in D, no, and there is no module in D. The parent class of D is C. Find the method of the C instance first, but there is module M in C, and the method in module M. This order is based on the sequence of the ancestor chain.
To what extent can this search be performed? For example, the ancestor chain represents the object class, which is the beginning of all objects in ruby. There is a module kernel. That is to say, if you define a method in the kernel, all objects in Ruby can use this method.
2. search methods when multiple identical methods exist
When multiple identical methods exist, the first method is matched.
As follows:
1 module M 2 def method 3 puts "this is method in module M" 4 end 5 end 6 7 module N 8 def method 9 puts "this is method in module N"10 end11 end12 13 class C14 include M15 include N16 end17 18 C.new.method19 p C.ancestors
Output result
This is method in Module N
[C, N, M, object, kernel, basicobject]
Class C contains two modules, m, n, m, and N, which have the method. So which one to call? If the method defined in ruby is in the same class, it overwrites the old method. Similarly, if Module N is backward mixed with M, such as class C, the method in N is called. On the other hand, from the perspective of the ancestor chain, n is also at the top of M, so n method is also called first.
How are modules sorted in the ancestor chain? In the ancestor chain, a module M is exactly located in the previous position of class C that contains it. In this example, Class C first contains m, which is C and M in the ancestor chain. Then it contains N, N, and exactly in the last position of C, so it becomes C, N, M.
3. search methods that contain Singleton classes
The preceding two cases do not include Singleton classes. If Singleton classes exist, you must first consider Singleton classes.
Singleton class: specifically, it is a class unique to an object. It can only belong to one object (even other object instances of the same class), so it is called a singleton class.
In Ruby, each object actually has two classes: Classes shared by multiple object instances and Singleton classes. The method called by the object is the instance method in the two classes, and the methods in the ancestor class and mixed modules.
When there is a singleton class, the object method first searches for Singleton classes, then modules that are mixed with Singleton classes, and then the class to which the object belongs, and so on.
The parent class of the singleton class is the class to which the object belongs.
As follows:
1 module M 2 def method 3 puts "this is method in module M" 4 end 5 end 6 7 class C 8 end 9 10 c = C.new11 class << c12 def method13 puts "this is method in c‘ singleton class"14 end15 include M16 p ancestors17 end18 19 c.method
The output is
[M, C, object, kernel, basicobject]
This is method in C 'singleton class
The Singleton class is not represented in the ancestor chain, but the called method is indeed a singleton class method. Then there is the mixed module M, then the parent class, and so on. As can be seen from the ancestor chain, the parent class of the singleton class is C, which is the class of Object C.
Help
A problem occurs here. If Class C also contains class module M, the ancestor chain should theoretically be m, C, M, object, kernel, basicobject.
As follows:
1 module M 2 end 3 class C 4 include M 5 end 6 c = C.new 7 class << c 8 include M 9 p ancestors10 end11 p C.ancestors
The output result is:
[C, M, object, kernel, basicobject]
[C, M, object, kernel, basicobject]
The modules mixed in the singleton class do not appear in the ancestor chain. The Singleton class of C is the same as the ancestor chain of class C.
Assume that class C contains not module M, but another module n.
As follows:
1 module M 2 end 3 module N 4 end 5 class C 6 include N 7 end 8 c = C.new 9 class << c10 include M11 p ancestors12 end13 p C.ancestors
Output result
[M, C, N, object, kernel, basicobject]
[C, N, object, kernel, basicobject]
At this time, the results are the same as I expected. In the ancestor chain, there are still modules M mixed with C Singleton classes.
Why? Does it mean that if the singleton class and other classes on the ancestor chain are mixed with the same module, the module name in the singleton class will not be displayed?
In addition, I also include m in the class object. The result is [C, N, object, M, kernel, basicobject], and the module M in the C Singleton class does not exist. If n is contained, the result is [M, C, N, object, N, kernel, basicobject], which is the same as expected. Is it because the singleton class and other classes on the ancestor chain cannot contain the same module?
I know that non-singleton classes can contain modules with the same name and can appear in the ancestor chain at the same time. (I use ruby1.9.3)
Thank you for your understanding and answers.
Singleton class of four methods
The preceding section describes the singleton class of an instance object. What if it is a class Singleton class? (Each object has a singleton class, and classes are also objects. Of course, there are also Singleton classes. Class methods are placed in singleton classes .)
A singleton class cannot be inherited, but a singleton class can have a parent class or subclass.
As follows:
1 class C 2 def self.method 3 p "This is method in C" 4 end 5 end 6 class D < C 7 end 8 D.method 9 10 en = class << C;self;end11 class E < en;end;
Output result
"This is method in C"
Can't make subclass of Singleton class (typeerror)
The result shows that D. method calls the singleton method of C, indicating that D's Singleton class inherits the singleton class of C and is its subclass. However, from lines 10-11, we can see that the singleton class cannot be inherited.
I think we can think that: when D inherits C, D's Singleton class inherits C's Singleton class, so d can call C's class method. Similarly, D can also call the class methods of the object class.
Sort it out:
Class, first find the singleton class, and then the module in the singleton class. Find the parent class, the module in the parent class. And so on.
Class Object Method Search, first find the singleton class (that is, the class method), then find the singleton class of the parent class, and so on.
If multiple methods are found, match the first method.
In Ruby, a class cannot be inherited, and it can also have subclasses. For example, a singleton class in ruby.
If we use superclass to find the parent class, we can get (# represents the singleton class. Suppose D is the object of class D, and Class D inherits Class C,-> indicates that the parent class is)
# D-> C-> Object-> basicobject-> Nil
# D-> # C-> # object-> # basicobject-> class-> module-> Object-> basicobject-> Nil