When calling a method, even if the method is defined in its own class Defined as a singular method in a superclass, module, or an instance created from a class I think there are various cases. This time, about the flow of method search in those cases I would like to summarize it.
class Klass
def hello
puts "Hello_from_Klass"
end
end
klass_obj = Klass.new
klass_obj.hello
# => Hello_from_Klass
It seems to be the simplest case.
When the hello
method is called on the obj
object
Browse to the direct class, the Klass class, and look for the hello
method there.
In this case, we were able to find it there, so the search ends there and the method is executed.
class Klass
def hello
puts "Hello from Klass"
end
end
class SubKlass < Klass
end
sub_klass_obj = SubKlass.new
sub_klass_obj.hello
# => Hello_from_Klass
For the search direction, first refer to the direct class, and if it is not there
That parent class, or even that parent class ...
Is equal to the class inheritance order.
In this case, it referred to SubKlass
and there was no hello
method.
Because the hello
method was defined by referring to its parent class Klass
The search ends and the method is executed.
class Klass
def hello
puts "Hello from Klass"
end
end
obj = Klass.new
def obj.hello
puts "Hello from singleton"
end
obj.hello
# => Hello from singleton
In this case, instead of the hello
method defined in the direct class
The hello
method defined as a singular method was called.
In other words, the singular class has its method searched before the object's class.
I understand.
Define a method with the same name in the superclass and module Try calling that method from an instance of a subclass.
module HelloModule
def hello
puts "Hello from HelloModule"
end
end
class Klass
def hello
puts "Hello from Klass"
end
end
class SubKlass < Klass
include HelloModule
end
sub_klass_obj = SubKlass.new
sub_klass_obj.hello
# => Hello from HelloModule
The hello
method of the included module was called.
The included modulue is between the included class and the parent class.
It will exist.
At this time, an anonymous class that seems to wrap the module is created and embedded in the inheritance tree.
By the way, this anonymous class cannot be touched by a Ruby program.
Because the anonymous class is created and embedded in the inheritance tree in this way
Method search can also be referenced with the same rules as when normal inheritance is done.
Earlier, I included only one module, module include is different from class inheritance You can include multiple modules for one class.
Let's actually include multiple modules and call the method.
module FirstModule
def hello
puts "Hello from FirstModule"
end
end
module SecondModule
def hello
puts "Hello from SecondModule"
end
end
class Klass
def hello
puts "Hello from Klass"
end
end
class SubKlass < Klass
include FirstModule
include SecondModule
end
sub_klass_obj = SubKlass.new
sub_klass_obj.hello
# => Hello from SecondModule
When multiple modules are included, The method of the module that was included last was called. When multiple modules are included in the same class in this way, Modules are embedded in the inheritance tree of the class in the order they are included.
First, FirstModule is included and becomes the following inheritance tree.
After that, when the SecondModule described below is included, it will be as follows.
This time, after reading in the order of FirstModule``SecondModule
as before
Try loading FirstModule
again.
module FirstModule
def hello
puts "Hello from FirstModule"
end
end
module SecondModule
def hello
puts "Hello from SecondModule"
end
end
class Klass
def hello
puts "Hello from Klass"
end
end
class SubKlass < Klass
include FirstModule
include SecondModule
include FirstModule
end
sub_klass_obj = SubKlass.new
sub_klass_obj.hello
# => Hello from SecondModule
The last include description is FirstModule
It was the method of SecondModule
that was called.
Actually, when inserting a class that wraps a module in the inheritance tree,
Checking for the same module in the inheritance tree.
Therefore, when the second include First Module
is called,
Because FirstModule
is already included
The include method ends without being plugged in.
module PrependModule
def hello
puts "Hello from PrependModule"
end
end
module IncludeModule
def hello
puts "Hello from IncludeModule"
end
end
class Klass
prepend PrependModule
include IncludeModule
def hello
puts "Hello from Klass"
end
end
klass_obj = Klass.new
klass_obj.hello
# => Hello from PrependModule
include includes an anonymous class that wraps a module
Whereas it is embedded above the included class
The prepend is embedded below that class. (The method is called with priority over the prepared class)
Therefore, if you call super
in the module to prepare,
The method with the same name in the prepend class is called.
module HelloModule
def hello
puts "Hello from FirstModule"
end
end
class Klass
def hello
puts "Hello from Klass"
end
end
class SubKlass < Klass
include HelloModule
end
obj = SubKlass.new
obj.bye
# => undefined method `bye' for #<SubKlass:0x00007fb5fb80c628> (NoMethodError)
I tried calling the bye
method that doesn't exist anywhere in the object
I spit out NoMethodError
.
When the bye method is called, it goes through the inheritance tree in order to find the method.
However, this time it is not defined anywhere, so after searching to the top of the inheritance tree, BasicObject
Go back to the direct class SubKlass
, and this time look for the method_missing
methods in the order of the inheritance tree.
This time it is the top level because I have not defined the method_missing
method myself
The method_missing
method of BasicObject
is called to raise a NoMethodError
as an exception.
Therefore, if there is a method_midding
method in the middle of the inheritance tree up to BasicObject
Call it.
module HelloModule
def hello
puts "Hello from FirstModule"
end
end
class Klass
def hello
puts "Hello from Klass"
end
def method_missing(method_name, *args)
puts "#{method_name}?There is no such method"
end
end
class SubKlass < Klass
include HelloModule
end
obj = SubKlass.new
obj.bye
# => bye?There is no such method
As a search flow
1, singular class of receiver
2, direct class
2', module if module is included
3, 2 parent classes
3', module if module is included
4, Repeat 3
until the method is found
5, If you do not search to the top of the inheritance tree (BasicObject
), the search with that method ends.
6, Using the method name as an argument, search for the method_missing
method from 1
7, If not, method_missing
of BasicObject
is called and an exception of NoMethodError
occurs.
Recommended Posts