CSC/ECE 517 Fall 2009/wiki2 5 jn
Reflection APIs (TOC)
Introduction
What is Reflection?
Reflection in programming is a technique in which programs are able to dynamically view and alter their own structure and flow. For example, in reflection one could determine method/variable/class names, add or delete method/variables, alter code to current methods, or simply alter values in variables. Reflection is a subset of MetaProgramming which relies heavily on the use of meta-information. Meta-Information is used to keep track of the program structure such as names of available methods,variables and classes but also is what really makes reflection possible. In theory there are nearly no bounds to reflection as it directly modifies the binary of the program. The current limitations of this process are related to the APIs avaliable for specific languages. Majority of object-oriented languages have the functionality built in and some like C++ require external libraries to achieve even the basic functionality of Reflection.
What languages are Supported?
Due to the complexity required to support this majority of the languages that support this feature tend to be object oriented. Some examples of supported languages are Java, Ruby, C#, Perl, PHP, JavaScript, Python, and ActionScript. In this page we will cover a select few of the languages above and what native API support is avaliable for each of the languages.
Terminology
- Reflection
- MetaProgramming
- Binding
Available Reflection APIs
Reflection in C#
Reflection in Java
Reflection in Ruby
The nature of Ruby as an object-oriented language gives great support for Reflection. The current support for reflection in ruby is built into the language and is accessable through certain fuctions within the standard Ruby API. The methods most commonly used for reflection in Ruby along with some basic examples of their usage are shown below.
Eval Method
The eval method is defined in the Kernel Module of Ruby and is used to evaluate literals encompased in strings. This may not seem useful but the eval method also work in the scope of bindings which represent the scope of execution at a particular place in the code. This allows programmers to view any variables in any scope for any instance. An example of eval's usage is shown below.
Example
class Test def initialize(var) @secret = n end def getBinding return binding() end end test1 = Test.new("12+5") #We can determine what test1's instance of secret is and evaluate it without an accessor method eval("@secret", test1.getBinding) #=> 17
I this example we can see that by acquiring the binding at some scope in the program we can use it to get inside the context of any object instance and determine the value of any instance variables.
Instance Eval Method
The instance_eval method is defined in the Object class and works within the instance of any class. This method performs much of the same operations as the eval method but works in the scope of an object without requiring the binding statement as above. In fact we can accomplish the same example as above with the code shown below.
Example
class Test def initialize(var) @secret = n end end test1 = Test.new("12+5") #We can determine what test1's instance of secret is and evaluate it without an accessor method test1.instance_eval { @secret } #=> 17
Again this code performs exactly the same thing as the prior example above. The result is 17 which is the evaluation of the string literal as a command.
Class Eval Method
The class_eval method is defined in the Module class and works within the instance of any class. This method can be used to work within the context of any object whether that is assigning or accessing variables, declaring instance methods, or even re-defining inherited methods. The method takes actions either via string literal or a block of code. An example of adding accesor methods to the previous Test class is shown in example 1.
Example 1
class Test def initialize(var) @secret = n end end test1 = Test.new("12+5") #We can determine what test1's instance of secret by creating an accessor method for this instance. test1.class_eval{ def getSecret; @secret; end } eval(test1.getSecret) #=> 17 #Or by simply accessing the local variable as below. eval(test1.class_eval{@secret}) #=> 17
This example shows the versatility of the class_eval method to work on any class instance. It performs many of the operations that the previous methods have performed but with the added advantage of assigning instance methods.
Example 2
class Test def initialize(var) @secret = n end private: def increment @secret += 1 end end test1 = Test.new(17) #We can directly use class_eval to call private methods within a class as well. test1.class_eval{ increment() } #=> 18
This example shows that class_eval has even more flexibility to call private functions of a class from outside of the class scope.
Reflection in PHP
Reflection in PERL
Reflection in ActionScript
Conclusions
Links
[2] Reflection in C# - CoderSource.net
[3]