In the Java language, a launch mechanism is provided by which the object can be constructed from a string, can get all the methods of the object (including private methods), can invoke the private method, and can change the value of the member variable (including the private member variable).
Ruby is also an object-oriented high-level language and, of course, provides a reflection mechanism, and today we discuss the ability to construct class objects through class names.
Constructing class objects by class name
Let's look at the ordinary structure:
Copy Code code as follows:
Module Modulea
#the class name, later we use it to create the corresponding object
Class_name_of_wood = "Modulea::wood"
Class_name_of_wooddesk = "Modulea::wooddesk"
Class_name_of_woodchair = "Modulea::woodchair"
Class Wood
DEF initialize
@desc = "I am a primal wood"
End
DEF say
Puts @desc
End
End
Class Wooddesk < Wood
DEF initialize
@desc = "I am a desk made of wood"
End
def say_private
Puts "Actually, I have some bug but no public"
End
Public:say
Private:say_private
End
Class Woodchair < Wood
DEF initialize
@desc = "I am a chair made of wood"
End
def say_private
Puts "I Want get married with a wooddesk ..."
End
def smile
Puts "ha hah hah haha ..."
End
Public:say
Private:say_private,: Smile
End
End
Defines a basic class wood, which has two subclasses: Wooddesk, Woodchair, and subclasses that have a private method say_private respectively.
We new objects to execute:
Copy Code code as follows:
#the Normal Initailze
Wood = Modulea::wood.new
Wood.say
Desk = Modulea::wooddesk.new
Desk.say
Chair = modulea::woodchair.new
Chair.say
#try Call the Private method
Puts "desk respond to say_private?" #{desk.respond_to?: say_private} "
Desk.say_private if desk.respond_to? : Say_private
The code above, executes the public method say, and then attempts to execute the private method say_private, whether the execution of the check is possible, and the return result is not enforceable, desk.respond_to? : Say_private returns false:
Copy Code code as follows:
I am a primal wood
I am a desk made of wood
I am a chair made of wood
Desk respond to say_private? False
OK, now we construct the object through the reflection mechanism and try to execute its private method.
We notice that there are three constants in the definition of the module, which is defined as the class name,
Copy Code code as follows:
#the class name, later we use it to create the corresponding object
Class_name_of_wood = "Modulea::wood"
Class_name_of_wooddesk = "Modulea::wooddesk"
Class_name_of_woodchair = "Modulea::woodchair"
The following three variables are used to understand the Module.constants method.
The following code fragment is based on the class definition above:
Copy Code code as follows:
#get All Module Constants
Obj_list = Array.new
Tmp_const_sym_list = modulea.constants
Tmp_const_sym_list.each do | Sym |
Obj_list << Modulea.const_get (sym)
Puts "CALSS = #{sym.class}, value = #{sym}"
End
We note that modulea.constants, which is in module modules, acts as a symbol object that returns all the constants in the module. We look at the result output:
Copy Code code as follows:
CALSS = Symbol, value = Class_name_of_wood
CALSS = Symbol, value = Class_name_of_wooddesk
CALSS = Symbol, value = Class_name_of_woodchair
CALSS = Symbol, value = Wood
CALSS = Symbol, value = Wooddesk
CALSS = Symbol, value = Woodchair
As you can see from the results, the three constants and class names that are defined are returned. So note: The constants in Ruby are the constants (variables) and class names that contain the definitions, and note that they are all symbol objects ...
But we need to construct the class object based on the class name, then the three constants are useless and need to be deleted. We filter by using regular expressions to match names. The code above modifies:
Copy Code code as follows:
#get All Module Constants
Sym_list = Array.new
Tmp_const_sym_list = modulea.constants
Tmp_const_sym_list.each do | Sym |
Puts "CALSS = #{sym.class}, value = #{sym}"
Sym_list << Modulea.const_get (sym) if/^wood\w*/=~ sym.to_s
End
Sym_list << Modulea.const_get (sym) if/^wood\w*/=~ sym.to_s, save only the symbol at the beginning of Wood, so that we filter out the three constants.
After looking for both class names, start constructing the object:
Copy Code code as follows:
#create object from Symbol
Obj_list = Array.new
Sym_list.each do | Sym |
obj = sym.new
Obj_list << obj
Puts "Create the object: #{obj}"
End
Begin
Obj_list.each do | Wood |
Wood.say
End
Call the new method of symbol to construct the secondary object (sym.new), and then we call the object's say method:
Copy Code code as follows:
Create the object: #
Create the object: #
Create the object: #
I am a primal wood
I am a desk made of wood
I am a chair made of wood
Achieved the results we had expected.
Operation member variables and private methods
Students who have used Java reflection know that with objects, manipulating member variables and private methods is a cinch.
The same is true in Ruby.
Look at the example of an operation member variable first. We tried to change the value of a member variable. (followed by the code of an article)
Copy Code code as follows:
#manpulate instance variables
First_wood = Obj_list.first
First_wood.instance_variables.each do | var |
#get the instance variable
Puts "class of var = #{var.class}, value of var = #{var}"
Var_value = First_wood.instance_variable_get (Var)
Puts "class of Var_value = #{var_value.class}, value of Var_value = #{var_value}"
#set the new value of instance Varialbe
First_wood.instance_variable_set (Var, var_value + "... and I was changed.")
First_wood.say
End
1, First_wood.instance_variables.each, we get a wood object, and then call its Instance_variables method to get the names of all the member variables (symbol objects).
2, then, call the object's First_wood.instance_variable_get method, pass the member variable name, get the member variable object.
3, finally, we change the value of this member variable through First_wood.instance_variable_set.
Code Run Results:
Copy Code code as follows:
Class of var = Symbol, value of var = @desc
Class of Var_value = String, value of Var_value = I am a primal wood
I am a primal wood...and I was changed.
Then look at the calling private method:
Copy Code code as follows:
#call Private Method
Last_wood = Obj_list.last
Last_wood.method (: say_private). Call
Quite simply, if you know the method name, call Last_wood.method the method name, you can get a methods object and call the method object, and the result is the contents of the private method output:
Copy Code code as follows:
I Want get married with a wooddesk ...
There is no way to modify a member variable and invoke a private method in a normal scenario, because it violates the object-oriented encapsulation principle, so what scenario is reflection useful? From my personal experience, I think two places are useful:
1) Unit Test.
2 aspect-oriented programming.
Both scenarios need to invoke the private method or replace the value of the member variable.
What do you think?