Reflection application instance in Ruby

Source: Internet
Author: User

In the Java language, the launch mechanism is provided. Through the launch mechanism, this object can be constructed using strings to obtain all methods of the object (including private methods) and call private methods, you can change the value of a member variable (including a private member variable ).
Ruby is also an object-oriented high-level language. Of course it also provides a reflection mechanism. Today we will discuss the function of constructing class objects through class names.

1. Construct class objects using class names

Let's first look at the common structure:

Copy codeThe Code is as follows:
Module ModuleA

# The class name, later we will 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 bugs 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 haha ...."

End


Public: say

Private: say_private,: smile

End

End

Defines a basic class Wood, which has two subclasses: WoodDesk and WoodChair. each subclass has a private method say_private.
We use the new output object to execute:

Copy codeThe Code is 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

In the above Code, run the public method say, and then try to execute the private method say_private. check whether the result can be executed first, and the returned result cannot be executed, desk. respond_to? : Say_private: false:

Copy codeThe Code is 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

Well, now we use the reflection mechanism to construct the object and try to execute its private method.

We noticed that there are three constants in the module definition, which define the class name,
Copy codeThe Code is as follows:

# The class name, later we will 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 snippet is defined based on the above class:

Copy codeThe Code is 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 noticed ModuleA. constants. This method is in the Module, and its function is to return the Symbol object of all constants in the Module. We can see the result output:

Copy codeThe Code is 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

The results show that the three defined constants and class names are returned. Note: constants in Ruby are defined constants (variables) and Class names. Note that they are all Symbol objects ..

However, if we need to construct a class object based on the class name, the three constants are useless and need to be deleted. We use regular expressions to match names. Modify the above Code:

Copy codeThe Code is 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, only save the symbol starting with Wood, so that we can filter out the three constants.

After the class name is found, the object is constructed:

Copy codeThe Code is 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 next object (sym. new). Then we call the say method of the object:

Copy codeThe Code is 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

We have achieved our expected results.

Ii. operating member variables and private methods

All the students who have used Java reflection know that when an object is available, the member variables and private methods will be ignored.
The same is true in Ruby.

First, let's look at the example of operating member variables. We try to change the value of a member variable. (The Code of the previous Article)

Copy codeThe Code is 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 call its instance_variables method to get the name of all member variables (Symbol object ).
2. Then, call the first_wood.instance_variable_get method of the object and pass the member variable name to obtain the member variable object.
3. Finally, we use first_wood.instance_variable_set to change the value of this member variable.
Code running result:

Copy codeThe Code is 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.

Let's call the private method again:

Copy codeThe Code is as follows:
# Call private method

Last_wood = obj_list.last

Last_wood.method (: say_private). call

If you know the Method name and call last_wood.method to pass in the Method name, you can get a Method object and then call the call Method of the Method object. The result is the output content of the private Method:

Copy codeThe Code is as follows:
I Want get married with a WoodDesk...

In common scenarios, member variables cannot be modified or private methods can be called, because this violates the object-oriented encapsulation principle. In what scenarios is reflection useful? In my personal experience, I think it is useful in two areas:
1) unit test.
2) Aspect-Oriented Programming.
Both scenarios require calling a private method or replacing the value of a member variable.

What do you think?

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.