CSC/ECE 517 Fall 2012/ch1b 1w40 ar: Difference between revisions
No edit summary |
No edit summary |
||
(111 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
==Introduction== | ==Introduction== | ||
By looking at the mirror, we can see our image and we can act on what we see like straightening the tie. In [http://en.wikipedia.org/wiki/Computer_programming Software programming], Reflection is a feature of some [http://en.wikipedia.org/wiki/Programming_language programming languages] and [http://en.wikipedia.org/wiki/Scripting_language scripting languages] that allows them to change their own structure at [http://en.wikipedia.org/wiki/Run_time_(program_lifecycle_phase) run-time]. For example in | By looking at the mirror, we can see our image and we can act on what we see like straightening the tie. In [http://en.wikipedia.org/wiki/Computer_programming Software programming], Reflection is a feature of some [http://en.wikipedia.org/wiki/Programming_language programming languages] and [http://en.wikipedia.org/wiki/Scripting_language scripting languages] that allows them to change their own structure at [http://en.wikipedia.org/wiki/Run_time_(program_lifecycle_phase) run-time]. For example in high level [http://en.wikipedia.org/wiki/Object-oriented_programming object oriented languages] the ability to inspect its [http://en.wikipedia.org/wiki/Class_(computer_science) class] [http://www.cs.utah.edu/~germain/PPS/Topics/interfaces.html interfaces] and [http://en.wikipedia.org/wiki/Method_(computer_science) methods] at run time without knowing their names at [http://en.wikipedia.org/wiki/Compile_time compile time]. It provides the ability to modify, instantiate and access to methods such as [http://en.wikipedia.org/wiki/Mutator_method getter's and setter's] of a class. Since the program need not have all the information at compile time it makes the program more dynamic. | ||
==Background== | ==Background== | ||
The earliest computers were programmed in their native [http://en.wikipedia.org/wiki/Assembly_language assembly language ], which is inherently reflective as it is programmed by defining the instructions as data. Reflective functionality such as modifying the instructions or analyzing them was commonplace. As programming moved to higher level languages such as C, this practice disappeared until programming languages with reflection in their type system appeared. Brian Cantwell Smith's 1982 doctoral dissertation<ref>[http://dspace.mit.edu/handle/1721.1/15961 Brian Cantwell | The earliest computers were programmed in their native [http://en.wikipedia.org/wiki/Assembly_language assembly language ], which is inherently reflective as it is programmed by defining the instructions as data. Reflective functionality such as modifying the instructions or analyzing them was commonplace. As programming moved to higher level languages such as [http://en.wikipedia.org/wiki/C_(programming_language) C], this practice disappeared until programming languages with reflection in their type system appeared. Brian Cantwell Smith's 1982 doctoral dissertation<ref>[http://dspace.mit.edu/handle/1721.1/15961 Brian Cantwell, Smith, <i>"Procedural Reflection in Programming Languages, Department of Electrical Engineering and Computer Science"</i>, Massachusetts Institute of Technology, PhD Thesis, 1982]</ref><ref>[http://publications.csail.mit.edu/lcs/specpub.php?id=840 Brian C. Smith, <i>"Reflection and semantics in a procedural language"</i>, Technical Report MIT-LCS-TR-272, Massachusetts Institute of Technology, Cambridge, Mass., January 1982]</ref> introduced the notion of computational reflection in programming languages, and the notion of the meta-circular interpreter as a component of 3-Lisp<ref>[http://weblog.raganwald.com/2006/11/significance-of-meta-circular_22.html Metacircular Interpreter and Lisp]</ref>. | ||
==Types of reflection== | ==Types of reflection== | ||
Line 9: | Line 9: | ||
* Behavioral Reflection: | * Behavioral Reflection: | ||
* Structural Reflection: | * Structural Reflection: | ||
===Behavioral Reflection | ===Behavioral Reflection=== | ||
=== | Behavioral refection is the ability to intercept an operation such as method invocation and alter the behavior of that operation. If an operation is intercepted, the run-time system calls a method on a [http://en.wikipedia.org/wiki/Metaobject meta-object] for notifying it of that event. The developers can define their own version of the meta-object so that the meta-object can execute the intercepted operation with customized semantics.<ref>[https://docs.google.com/viewer?a=v&q=cache:i6KjZI0O8GMJ:www.dcs.bbk.ac.uk/research/techreps/2003/bbkcs-03-02.pdf+&hl=en&gl=us&pid=bl&srcid=ADGEESjrOE_8g8LK17s4aMSJGnlCTQYrqYOjV2kwE6UqjeqUAJB4aS9lr6mC2vGjTgOBoUx0x4P1ZpiLVn5FNILdj94H-agO8G7VR7gifRFBF-DFmG56xad0rKGZKTuiTo0j6-cYC7ko&sig=AHIEtbTO49mzmKh7b7TgL8arl4SA4_NyZw Youssef Hassoun, Roger Johnson,Steve Counsell,<i> "Reusability, Open Implementation and Java’s Dynamic Proxies"</i>,School of Computer Science and Information Systems] </ref>. Behavioral | ||
This type of reflection deals with changing the very structure of the program such as the data structures and flow of control in the program. | reflection focuses on the application’s [http://en.wikipedia.org/wiki/Computational_semantics computational semantics]. For instance, a [http://en.wikipedia.org/wiki/Distributed_application distributed application] can use behavioral reflection to select and load a [http://en.wikipedia.org/wiki/Communications_protocol communication protocol] well suited to current [http://en.wikipedia.org/wiki/Computer_network network conditions] <ref>[http://di.ufpe.br/~redis/middleware/mckinley-composition04.pdf Philip K. McKinley, Seyed Masoud Sadjadi, Eric P.Kasten, Betty H.C.Cheng, <i>"Composing Adaptive Software"</i>, Michigan State University, July 2004.]</ref>.However, behavioral refection only provides the ability to alter the behavior of operation and does not provide the ability to alter [http://en.wikipedia.org/wiki/Data_structure data structures] used by the program statically fixed at compile time. | ||
===Structural Reflection=== | |||
This type of reflection deals with changing the very structure of the program such as the data structures and flow of control in the program <ref>[http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.1.6577 Load Time Structural Reflection]</ref>. Structural reflection addresses issues related to class [http://en.wikipedia.org/wiki/Hierarchy hierarchy], object interconnection, and [http://en.wikipedia.org/wiki/Data_type data types]. As an example, a metalevel object can examine a baselevel object to determine what methods are available for invocation. | |||
==Implementation== | ==Implementation== | ||
There are many challenges faced by designers of reflective languages. They must provide as much leeway as possible for late binding and at the same time they must optimize the compilation of the static | There are many challenges faced by designers of reflective languages. They must provide as much leeway as possible for [http://en.wikipedia.org/wiki/Late_binding late binding] and at the same time they must optimize the compilation of the static components so that they are ready for run-time. Reflection is in essence a connection between the object-level (program) and meta-level (the processor). The ability of the object level to be able to observe and modify the meta-level information is the consequence of this connection. These actions can be termed as [http://en.wikipedia.org/wiki/Type_introspection introspection].(This involves the action of observing the class) and intercession (this involves the operation of modifying the [http://en.wikipedia.org/wiki/Class_(computer_programming)#Behavior behavior] of the class). These actions can implemented with of the following components: | ||
* Ability to create [http://en.wikipedia.org/wiki/First-class_object | * Ability to create first class [http://en.wikipedia.org/wiki/First-class_object objects] ie [http://en.wikipedia.org/wiki/Reification_(computer_science) reification]. | ||
* Ability to convert a string that denotes a class or a method into its corresponding reference or invocation. | * Ability to convert a string that denotes a class or a method into its corresponding reference or invocation. | ||
* Ability to use and create symbolic links to methods and classes. | * Ability to use and create [http://en.wikipedia.org/wiki/Symbolic_link symbolic links] to methods and classes. | ||
Common languages that exhibit reflection to varying degrees are Ruby, Java, Smalltalk, C# and more.We have primarily focused on Java and C# as these are widely used object oriented languages. | Common languages that exhibit reflection to varying degrees are Ruby, Java, Smalltalk, [http://en.wikipedia.org/wiki/C_Sharp_(programming_language) C#] and more. We have primarily focused on Java and C# as these are widely used object oriented languages. | ||
===Ruby=== | ===Ruby=== | ||
[http://en.wikipedia.org/wiki/Ruby_(programming_language) Ruby] Reflection allows program entities to discover things about themselves through introspection. | [http://en.wikipedia.org/wiki/Ruby_(programming_language) Ruby] Reflection allows program entities to discover things about themselves through introspection. | ||
For example, an object can ask what its methods are, and a class can tell what its ancestors are. | For example, an [http://en.wikipedia.org/wiki/Object_(computer_science) object] can ask what its methods are, and a class can tell what its ancestors are. | ||
While Java also provides reflection, it does so much more verbosely than Ruby. | While Java also provides reflection, it does so much more verbosely than Ruby. | ||
Line 53: | Line 55: | ||
===Java=== | ===Java=== | ||
[http://en.wikipedia.org/wiki/Java_(programming_language) Java] Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine. | [http://en.wikipedia.org/wiki/Java_(programming_language) Java] Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the [http://en.wikipedia.org/wiki/Java_virtual_machine Java virtual machine]. | ||
====Key Features:==== | ====Key Features==== | ||
*Extensibility Features | The most luring feature is that one can access the metadata of classes and methods, getting the annotations and analyzing them dynamically. Other Advantages are as listed below: | ||
An application may make use of external, user-defined classes by creating instances of extensible objects using their fully-qualified names. | ====Advantages==== | ||
*<b>Extensibility Features</b> | |||
An application may make use of external, user-defined classes by creating [http://en.wikipedia.org/wiki/Instance_(computer_science) instances] of extensible objects using their fully-qualified names. | |||
*Class Browsers and Visual Development Environments | *<b>Class Browsers and Visual Development Environments</b> | ||
A class browser needs to be able to enumerate the members of classes. Visual development environments can benefit from making use of type information available in reflection to aid the developer in writing correct code. | A [http://en.wikipedia.org/wiki/Class_browser class browser] needs to be able to [http://en.wikipedia.org/wiki/Enumeration enumerate] the members of classes. [http://en.wikipedia.org/wiki/Visual_programming Visual development environments] can benefit from making use of type information available in reflection to aid the developer in writing correct code. | ||
*Debuggers and Test Tools | *<b>Debuggers and Test Tools</b> | ||
Debuggers need to be able to examine private members on classes. Test harnesses can make use of reflection to systematically call a | [http://en.wikipedia.org/wiki/Debugger Debuggers] need to be able to examine [http://en.wikipedia.org/wiki/Class_(computer_programming)#Member_accessibility private] members on classes. Test harnesses can make use of reflection to systematically call a discover-able set [http://en.wikipedia.org/wiki/Application_programming_interface APIs] defined on a class, to insure a high level of [http://en.wikipedia.org/wiki/Code_coverage code coverage] in a [http://en.wikipedia.org/wiki/Test_suite test suite]. | ||
*Retrieving Class Objects <ref>[http://docs.oracle.com/javase/tutorial/reflect/class/classNew.html JavaDoc for Reflection]</ref> | *<b>Retrieving Class Objects </b><ref>[http://docs.oracle.com/javase/tutorial/reflect/class/classNew.html JavaDoc for Reflection]</ref> | ||
The entry point for all reflection operations is java.lang.Class. With the exception of java.lang.reflect.ReflectPermission, none of the classes in java.lang.reflect have public constructors. To get to these classes, it is necessary to invoke appropriate methods on Class. There are several ways to get a Class depending on whether the code has access to an object, the name of class, a type, or an existing Class. | The entry point for all reflection operations is java.lang.Class. With the exception of java.lang.reflect.ReflectPermission, none of the classes in java.lang.reflect have public [http://en.wikipedia.org/wiki/Constructor_(object-oriented_programming) constructors]. To get to these classes, it is necessary to invoke appropriate methods on Class. There are several ways to get a Class depending on whether the code has access to an object, the name of class, a type, or an existing Class. | ||
<pre> | <pre> | ||
Object.getClass() | Object.getClass() | ||
</pre> | </pre> | ||
If an instance of an object is available, then the simplest way to get its Class is to invoke Object.getClass(). Of course, this only works for reference types which all inherit from Object. Some examples follow. | If an instance of an object is available, then the simplest way to get its Class is to invoke Object.getClass(). Of course, this only works for [http://en.wikipedia.org/wiki/Reference_type reference types] which all [http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming) inherit] from Object. Some examples follow. | ||
<pre> | <pre> | ||
Line 78: | Line 82: | ||
The .class Syntax: | The .class Syntax: | ||
If the type is available but there is no instance then it is possible to obtain a Class by appending ".class" to the name of the type. This is also the easiest way to obtain the Class for a primitive type. | If the type is available but there is no instance then it is possible to obtain a Class by appending ".class" to the name of the type. This is also the easiest way to obtain the Class for a [http://en.wikipedia.org/wiki/Primitive_data_type primitive type]. | ||
<pre> | <pre> | ||
Line 86: | Line 90: | ||
</pre> | </pre> | ||
Note that the statement boolean.getClass() would produce a compile-time error because a boolean is a primitive type and cannot be | Note that the statement boolean.getClass() would produce a compile-time error because a [http://en.wikipedia.org/wiki/Boolean_data_type boolean] is a primitive type and cannot be [http://en.wikipedia.org/wiki/Dereference_operator de-referenced]. The .class syntax returns the Class corresponding to the type boolean. | ||
TYPE Field for Primitive Type Wrappers: | TYPE Field for [http://en.wikipedia.org/wiki/Primitive_wrapper_class Primitive Type Wrappers]: | ||
The .class syntax is a more convenient and the preferred way to obtain the Class for a primitive type; however there is another way to acquire the Class. Each of the primitive types and void has a wrapper class in java.lang that is used for boxing of primitive types to reference types. Each wrapper class contains a field named TYPE which is equal to the Class for the primitive type being wrapped. | The .class syntax is a more convenient and the preferred way to obtain the Class for a primitive type; however there is another way to acquire the Class. Each of the primitive types and void has a wrapper class in java.lang that is used for boxing of primitive types to reference types. Each [http://en.wikipedia.org/wiki/Primitive_wrapper_class wrapper class] contains a field named TYPE which is equal to the Class for the primitive type being wrapped. | ||
<pre> | <pre> | ||
Line 97: | Line 101: | ||
Methods that Return Classes: | Methods that Return Classes: | ||
There are several Reflection APIs which return classes but these may only be accessed if a Class has already been obtained either directly or indirectly. | There are several [http://en.wikiversity.org/wiki/Java_Tutorial/Trail:_The_Reflection_API Reflection APIs] which return classes but these may only be accessed if a Class has already been obtained either directly or indirectly. | ||
<pre>Class.getSuperclass()</pre> | <pre>Class.getSuperclass()</pre> | ||
Returns the super class for the given class. | Returns the [http://en.wikipedia.org/wiki/Superclass_(computer_science)#Subclasses_and_superclasses super class] for the given class. | ||
<pre>Class c = javax.swing.JButton.class.getSuperclass();</pre> | <pre>Class c = javax.swing.JButton.class.getSuperclass();</pre> | ||
Line 106: | Line 110: | ||
<pre>Class.getClasses()</pre> | <pre>Class.getClasses()</pre> | ||
Returns all the public classes, interfaces, and enums that are members of the class including inherited members. | Returns all the public classes, interfaces, and [http://en.wikipedia.org/wiki/Enum enums] that are members of the class including inherited members. | ||
<pre>Class[] c = Character.class.getClasses();</pre> | <pre>Class[] c = Character.class.getClasses();</pre> | ||
Character contains two member classes Character.Subset and Character.UnicodeBlock. | Character contains two member classes [http://docs.oracle.com/javase/7/docs/api/java/lang/Character.Subset.html Character.Subset] and Character.UnicodeBlock. | ||
<pre>Class.getDeclaredClasses()</pre> | <pre>Class.getDeclaredClasses()</pre> | ||
Line 123: | Line 127: | ||
java.lang.reflect.Constructor.getDeclaringClass() | java.lang.reflect.Constructor.getDeclaringClass() | ||
</pre> | </pre> | ||
Returns the Class in which these members were declared. Anonymous Class Declarations will not have a declaring class but will have an enclosing class. | Returns the Class in which these members were declared. [http://en.wikipedia.org/wiki/Class_(computer_programming) Anonymous Class Declarations] will not have a declaring class but will have an enclosing class. | ||
<pre>import java.lang.reflect.Field; | <pre>import java.lang.reflect.Field; | ||
Line 139: | Line 143: | ||
} | } | ||
</pre> | </pre> | ||
The declaring class of the anonymous class defined by o is null. | The declaring class of the anonymous class defined by the object "o" is null. | ||
====Disadvantages | ====Disadvantages==== | ||
Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection. | Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection. | ||
*Performance Overhead | *<b>Performance Overhead</b> | ||
Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications. | Because reflection involves types that are dynamically resolved, certain [http://en.wikipedia.org/wiki/Java_performance#Virtual_machine_optimization_techniques Java virtual machine optimizations] can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications. | ||
*Security Restrictions | *<b>Security Restrictions</b> | ||
Reflection requires a run-time permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet. | Reflection requires a run-time permission which may not be present when running under a [http://en.wikipedia.org/wiki/Information_security_management security manager]. This is in an important consideration for code which has to run in a restricted security context, such as in an [http://en.wikipedia.org/wiki/Applet Applet]. | ||
*Exposure of Internals | *<b>Exposure of Internals</b> | ||
Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform. | Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy [http://en.wikipedia.org/wiki/Software_portability portability]. Reflective code, breaks [http://en.wikipedia.org/wiki/Data_abstraction abstractions] and therefore may change behavior with upgrades of the [http://en.wikipedia.org/wiki/Computing_platform platform] <ref>[http://docs.oracle.com/javase/tutorial/reflect/index.html Disadvantages of Java Reflection API]</ref> | ||
===C#=== | ===C#=== | ||
====Key Features:==== | ====Key Features==== | ||
*Signature Based Polymorphism | It enables you to do simple things like: | ||
[http:// | Check the type of an object at runtime (simple calls to typeof() for example) | ||
Inspect the Attributes of an object at runtime to change the behavior of a method (the various serialization methods in .NET) | |||
To much more complicated tasks like: | |||
Loading an assembly at runtime, finding a specific class, determining if it matches a given Interface, and invoking certain members dynamically. | |||
====Advantages==== | |||
*<b>Signature Based Polymorphism</b> | |||
[http://msdn.microsoft.com/en-us/library/ms173183(v=vs.80).aspx C#] programmers are familiar with [http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming polymorphism] based on interface inheritance. Reflection provides an alternative where we can invoke methods having same [http://en.wikipedia.org/wiki/Type_signature signature], from different classes not having a common interface. | |||
*Inspecting and Manipulating Classes | *<b>Inspecting and Manipulating Classes</b> | ||
If we need to write code that depends on class details known only at run time, then reflection comes as an easy way to proceed. | If we need to write code that depends on class details known only at run time, then reflection comes as an easy way to proceed. | ||
*Creating Adaptable and Flexible Solutions | *<b>Creating Adaptable and Flexible Solutions</b> | ||
It is possible to write code for [http://en.wikipedia.org/wiki/Factory_method_pattern factory design pattern] by loading classes using reflection instead of writing fixed code depending on specific static types with if-else statements inside the factory method. | It is possible to write code for [http://en.wikipedia.org/wiki/Factory_method_pattern factory design pattern] by loading classes using reflection instead of writing fixed code depending on specific static types with if-else statements inside the factory method. | ||
Example: | <b>Example:</b> | ||
To write a C# .Net program which uses reflection, the program should use the namespace System.Reflection. To get type of the object, the typeof operator can be used. | To write a C# .Net program which uses reflection, the program should use the [http://en.wikipedia.org/wiki/Namespace namespace] System.Reflection. | ||
To get type of the object, the typeof operator can be used. There is one more method GetType() which also can be used for retrieving the type information of a class. The Operator "typeof" allows us to get class name of our object and GetType() method is used to get data about object's type. Suppose we have following class: | |||
There is one more method GetType() | |||
and GetType() method | |||
<pre> | <pre> | ||
Line 201: | Line 208: | ||
</pre> | </pre> | ||
At first we should get type of object that was created. The following C# .Net code snippet shows how to do it. | At first we should get type of object that was created. The following C# .Net code snippet shows how to do it <ref>[http://www.codersource.net/microsoft-net/c-basics-tutorials/c-net-tutorial-reflection.aspx C# Reflection]</ref> | ||
<pre> | <pre> | ||
TestDataType testObject = new TestDataType(15); | TestDataType testObject = new TestDataType(15); | ||
Line 207: | Line 214: | ||
</pre> | </pre> | ||
Now objectType has all the required information about class TestDataType. We can check if our class is abstract or if it is a class. The System.Type contains a few properties to retrieve the type of the class: IsAbstract, IsClass. These functions return a Boolean value if the object is abstract or of class type. Also there are some methods that return information about constructors and methods that belong to the current type (class). It can be done in a way as it | Now objectType has all the required information about class TestDataType. We can check if our class is abstract or if it is a class. The System.Type contains a few properties to retrieve the type of the class: IsAbstract, IsClass. These functions return a Boolean value if the object is abstract or of class type. Also there are some methods that return information about constructors and methods that belong to the current type (class). It can be done in a way as it is done in next example: | ||
<pre> | <pre> | ||
Type objectType = testObject.GetType(); | Type objectType = testObject.GetType(); | ||
Line 232: | Line 239: | ||
Now, the above program returns a list of methods and constructors of TestDataType class. | Now, the above program returns a list of methods and constructors of TestDataType class. | ||
====Disadvantages | ====Disadvantages==== | ||
*Exposes Implementation Details | *<b>Exposes Implementation Details</b> | ||
Use of reflection exposes much of the implementation details such as the methods, fields, accessibility and other | Use of reflection exposes much of the implementation details such as the methods, fields, [http://en.wikipedia.org/wiki/Class_(computer_programming)#Member_accessibility accessibility] and other [http://en.wikipedia.org/wiki/Metadata_(CLI) metadata] of the class used. | ||
*Performance | *<b>Performance</b> | ||
The code that is reflective is slow than the direct code that performs the same functionality. As reflection performance also depends | The code that is reflective is slow than the direct code that performs the same functionality. As reflection performance also depends on the kind of operations that are done in the code like creating objects, accessing members, making method calls, etc. | ||
===Smalltalk=== | ===Smalltalk=== | ||
Line 256: | Line 263: | ||
==Comparison of Reflection in different languages== | ==Comparison of Reflection in different languages== | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 270: | Line 278: | ||
| Supports Reflection | | Supports Reflection | ||
| Supports Reflection | | Supports Reflection | ||
| Poor support for Reflection | | Poor support for Reflection <ref>[http://grid.cs.binghamton.edu/projects/publications/c++-HPC07/c++-HPC07.pdf Tharaka Devadithya, Kenneth Chiu, Wei Lu, <i>"Reflection for High Performance Problem Solving Environments"</i>, Computer Science Department, Indiana University, 2007]</ref> | ||
|- | |- | ||
| Not Powerful and flexible as Ruby | | Not Powerful and flexible as Ruby Reflection | ||
| | | Provides powerful and flexible Reflection mechanism | ||
| Not Powerful and flexible as Ruby | | Not Powerful and flexible as Ruby | ||
| Powerful and flexible | | Powerful and flexible | ||
| | | Provides [http://en.wikipedia.org/wiki/Run-time_type_information RTTI ] support which provides only a very restricted subset of reflection | ||
|- | |- | ||
| Uses Reflection | | Uses Reflection | ||
| Ability to [ http://en.wikipedia.org/wiki/Type_introspection introspect ] | | Ability to [http://en.wikipedia.org/wiki/Type_introspection introspect ] as it is a dynamic language | ||
| Uses Reflection | | Uses Reflection | ||
| Ability to type introspect as it is a dynamic language | | Ability to type introspect as it is a dynamic language | ||
| | | C++ supports type introspection via the [http://en.wikipedia.org/wiki/Typeid typeid] and [http://en.wikipedia.org/wiki/Dynamic_cast dynamic_cast] keywords | ||
|- | |- | ||
| Variable's type determines its class and methods. | | Variable's type determines its class and methods. | ||
| Ruby supports liberated objects(cannot tell exactly what an object can do until you look | | Ruby supports liberated objects(cannot tell exactly what an object can do until you look under its hood) | ||
| Variable's type determines its class and methods. | | Variable's type determines its class and methods. | ||
| Uses Reflection class | | Uses Reflection class | ||
Line 295: | Line 302: | ||
|- | |- | ||
| Java Reflection API is a bit higher level than C# Reflection API. | | Java Reflection API (is a bit higher level than the C# Reflection API) <ref>[http://mydov.blogspot.com/2012/05/reflection-in-java-c-but-not-in-c.html Difference between Java and C# Reflection APIs]</ref> | ||
| Ruby has a rich set of Reflection APIs | | Ruby has a rich set of Reflection APIs | ||
| | | Has Reflection APIs | ||
| Has Reflection APIs | | Has Reflection APIs | ||
| Has no Reflection APIs | | Has no Reflection APIs | ||
|} | |} | ||
==Applications of Reflection== | ==Applications of Reflection== | ||
*Reflection has become invaluable to programmers who need to connect code with data. For example in a GUI environment a button might need to invoke different methods in different classes. Reflection can be used here to call the method on any given class. | *Reflection has become invaluable to programmers who need to connect code with data. For example in a [http://en.wikipedia.org/wiki/Graphical_user_interface GUI] environment, a button might need to invoke different methods in different classes. Reflection can be used here to call the method on any given class. | ||
*Programmers who deal with a multitude of classes at the same time can use reflection to create a | *Programmers who deal with a multitude of classes at the same time can use reflection to create a [http://en.wikipedia.org/wiki/Serializer serializer] that for a given class uses reflection to go through all the instance variables and processes them accordingly. | ||
*Reflection is used in large test frameworks where reflection helps in identifying the test methods for different scenarios. | *Reflection is used in large test frameworks where reflection helps in identifying the [http://en.wikipedia.org/wiki/Test_method test methods] for different scenarios. | ||
*Reflection provides the ability to morph the code based on dynamic situations. This provides a sense of artificial intelligence to the program as whole. | *Reflection provides the ability to [http://en.wikipedia.org/wiki/Code_morphing morph the code] based on dynamic situations. This provides a sense of [http://en.wikipedia.org/wiki/Artificial_intelligence artificial intelligence] to the program as whole. | ||
*Reflection can be used to debug and verify code as it provides access to the insides of a program. | *Reflection can be used to debug and verify code as it provides access to the insides of a program. | ||
Line 317: | Line 323: | ||
*Reflection is very useful when the software is upgraded regularly. It provides an easy method to check for available methods and classes. This prevents the errors caused by the absence of methods and classes when they are deprecated. | *Reflection is very useful when the software is upgraded regularly. It provides an easy method to check for available methods and classes. This prevents the errors caused by the absence of methods and classes when they are deprecated. | ||
==Advantages and disadvantages of reflection | ==Advantages and disadvantages of reflection== | ||
===Advantages=== | ===Advantages=== | ||
* Extensibility: Reflection provides the capability of using external and user defined classes by instantiation of extensibility objects using their fully qualified names. | * <b>Extensibility:</b> Reflection provides the capability of using external and user defined classes by instantiation of extensibility objects using their fully qualified names. | ||
* Class browsers in [http://en.wikipedia.org/wiki/IDE IDEs]: The ability to examine the members of classes makes implementation of visual aids , auto-completion and documentation easy in development tools for programmers. | * <b>Class browsers in [http://en.wikipedia.org/wiki/IDE IDEs]:</b> The ability to examine the members of classes makes implementation of visual aids , [http://en.wikipedia.org/wiki/Autocomplete auto-completion] and [http://en.wikipedia.org/wiki/Software_documentation documentation] easy in development tools for programmers. | ||
* [http://en.wikipedia.org/wiki/Debugging Debugging]: Reflection allows the user to observe the private members in classes. This capability can be used to debug classes and their interactions. | * <b>[http://en.wikipedia.org/wiki/Debugging Debugging]:</b> Reflection allows the user to observe the private members in classes. This capability can be used to debug classes and their interactions. | ||
* [http://en.wikipedia.org/wiki/Test_harness Test Harness] : Reflection can be used to call a set of testing APIs defined on a class for maximum coverage of testing. | * <b>[http://en.wikipedia.org/wiki/Test_harness Test Harness]:</b> Reflection can be used to call a set of testing APIs defined on a class for maximum coverage of testing. | ||
* Correctness : Reflection improves the robustness and the correctness of a program especially in dynamically typed languages as | * <b>Correctness</b> : Reflection improves the robustness and the correctness of a program especially in dynamically typed languages as run time checks can be added to check the availability of the methods or classes. | ||
===Disadvantages=== | ===Disadvantages=== | ||
* Reflection introduces lot of performance overhead when compared to non-reflective code. Hence it should be used judiciously. | * Reflection introduces lot of performance overhead when compared to non-reflective code. Hence it should be used judiciously. | ||
* Since it provides access to the internals of a class or an encapsulated object security becomes a major issue. | * Since it provides access to the internals of a class or an encapsulated object security becomes a major issue. | ||
* Since it is run-time binding we lose the security of compile time checks and verification. | * Since it is run-time binding we lose the security of compile time checks and verification <ref>[https://docs.google.com/a/ncsu.edu/viewer?a=v&q=cache:bnm9xJhl8EkJ:www.ics.uci.edu/~lopes/teaching/inf212W12/lectures/INF212-Reflection.pptx+reflection+analysis+over+ruby+java+c%23&hl=en&gl=us&pid=bl&srcid=ADGEESgNhIwaccNOPEKsCXmB8wZYIb4ZkP7HfShvDyrJOrI2z1Octe68TIM-DszvvTM5MZdFcJkT5NV5cSHrkxNICJya-VcIfqB22M2AvoBT5KmpvNV3lwUfhOgSKEGBu0gqtxJOK-aq&sig=AHIEtbTsPbOfryUJKCgMqZ6W2wbA522bCQ Analysis of Programming Languages]</ref> | ||
==Conclusion== | ==Conclusion== | ||
Line 344: | Line 350: | ||
*[http://ruby-doc.org/docs/ProgrammingRuby/html/builtins.html Ruby Documentation] | *[http://ruby-doc.org/docs/ProgrammingRuby/html/builtins.html Ruby Documentation] | ||
*[http://www.slideshare.net/MarcusDenker/behavioral-reflection Behavioral reflection] | *[http://www.slideshare.net/MarcusDenker/behavioral-reflection Behavioral reflection] | ||
*[http://msdn.microsoft.com/en-us/library/67ef8sbd(v=vs.80).aspx C# Basics] | |||
*[http://msdn.microsoft.com/en-us/library/ms173183(v=vs.80).aspx C# Reflection basics] | |||
*[http://www.codeguru.com/csharp/csharp/cs_misc/reflection/article.php/c4257/An-Introduction-to-Reflection-in-C.htm Introduction to C# Reflection] | |||
*[http://oreilly.com/catalog/progcsharp/chapter/ch18.html C# Attributes and Reflection] |
Latest revision as of 00:11, 11 October 2012
Introduction
By looking at the mirror, we can see our image and we can act on what we see like straightening the tie. In Software programming, Reflection is a feature of some programming languages and scripting languages that allows them to change their own structure at run-time. For example in high level object oriented languages the ability to inspect its class interfaces and methods at run time without knowing their names at compile time. It provides the ability to modify, instantiate and access to methods such as getter's and setter's of a class. Since the program need not have all the information at compile time it makes the program more dynamic.
Background
The earliest computers were programmed in their native assembly language , which is inherently reflective as it is programmed by defining the instructions as data. Reflective functionality such as modifying the instructions or analyzing them was commonplace. As programming moved to higher level languages such as C, this practice disappeared until programming languages with reflection in their type system appeared. Brian Cantwell Smith's 1982 doctoral dissertation<ref>Brian Cantwell, Smith, "Procedural Reflection in Programming Languages, Department of Electrical Engineering and Computer Science", Massachusetts Institute of Technology, PhD Thesis, 1982</ref><ref>Brian C. Smith, "Reflection and semantics in a procedural language", Technical Report MIT-LCS-TR-272, Massachusetts Institute of Technology, Cambridge, Mass., January 1982</ref> introduced the notion of computational reflection in programming languages, and the notion of the meta-circular interpreter as a component of 3-Lisp<ref>Metacircular Interpreter and Lisp</ref>.
Types of reflection
There are two basic types of reflection. They are:
- Behavioral Reflection:
- Structural Reflection:
Behavioral Reflection
Behavioral refection is the ability to intercept an operation such as method invocation and alter the behavior of that operation. If an operation is intercepted, the run-time system calls a method on a meta-object for notifying it of that event. The developers can define their own version of the meta-object so that the meta-object can execute the intercepted operation with customized semantics.<ref>Youssef Hassoun, Roger Johnson,Steve Counsell, "Reusability, Open Implementation and Java’s Dynamic Proxies",School of Computer Science and Information Systems </ref>. Behavioral reflection focuses on the application’s computational semantics. For instance, a distributed application can use behavioral reflection to select and load a communication protocol well suited to current network conditions <ref>Philip K. McKinley, Seyed Masoud Sadjadi, Eric P.Kasten, Betty H.C.Cheng, "Composing Adaptive Software", Michigan State University, July 2004.</ref>.However, behavioral refection only provides the ability to alter the behavior of operation and does not provide the ability to alter data structures used by the program statically fixed at compile time.
Structural Reflection
This type of reflection deals with changing the very structure of the program such as the data structures and flow of control in the program <ref>Load Time Structural Reflection</ref>. Structural reflection addresses issues related to class hierarchy, object interconnection, and data types. As an example, a metalevel object can examine a baselevel object to determine what methods are available for invocation.
Implementation
There are many challenges faced by designers of reflective languages. They must provide as much leeway as possible for late binding and at the same time they must optimize the compilation of the static components so that they are ready for run-time. Reflection is in essence a connection between the object-level (program) and meta-level (the processor). The ability of the object level to be able to observe and modify the meta-level information is the consequence of this connection. These actions can be termed as introspection.(This involves the action of observing the class) and intercession (this involves the operation of modifying the behavior of the class). These actions can implemented with of the following components:
- Ability to create first class objects ie reification.
- Ability to convert a string that denotes a class or a method into its corresponding reference or invocation.
- Ability to use and create symbolic links to methods and classes.
Common languages that exhibit reflection to varying degrees are Ruby, Java, Smalltalk, C# and more. We have primarily focused on Java and C# as these are widely used object oriented languages.
Ruby
Ruby Reflection allows program entities to discover things about themselves through introspection. For example, an object can ask what its methods are, and a class can tell what its ancestors are. While Java also provides reflection, it does so much more verbosely than Ruby.
Sample Code:
3.14159.methods puts [1, 2, 3, 4, 5].length Output: 5 puts "Hey".class Output: String puts "John".class.superclass # print the superclass of a String Output: Object puts String.ancestors #print the hierarchy Output: String Enumerable Comparable Object Kernel
Java
Java Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine.
Key Features
The most luring feature is that one can access the metadata of classes and methods, getting the annotations and analyzing them dynamically. Other Advantages are as listed below:
Advantages
- Extensibility Features
An application may make use of external, user-defined classes by creating instances of extensible objects using their fully-qualified names.
- Class Browsers and Visual Development Environments
A class browser needs to be able to enumerate the members of classes. Visual development environments can benefit from making use of type information available in reflection to aid the developer in writing correct code.
- Debuggers and Test Tools
Debuggers need to be able to examine private members on classes. Test harnesses can make use of reflection to systematically call a discover-able set APIs defined on a class, to insure a high level of code coverage in a test suite.
- Retrieving Class Objects <ref>JavaDoc for Reflection</ref>
The entry point for all reflection operations is java.lang.Class. With the exception of java.lang.reflect.ReflectPermission, none of the classes in java.lang.reflect have public constructors. To get to these classes, it is necessary to invoke appropriate methods on Class. There are several ways to get a Class depending on whether the code has access to an object, the name of class, a type, or an existing Class.
Object.getClass()
If an instance of an object is available, then the simplest way to get its Class is to invoke Object.getClass(). Of course, this only works for reference types which all inherit from Object. Some examples follow.
Class c = "foo".getClass();
Returns the Class for String.
The .class Syntax: If the type is available but there is no instance then it is possible to obtain a Class by appending ".class" to the name of the type. This is also the easiest way to obtain the Class for a primitive type.
boolean b; Class c = b.getClass(); // compile-time error Class c = boolean.class; // correct
Note that the statement boolean.getClass() would produce a compile-time error because a boolean is a primitive type and cannot be de-referenced. The .class syntax returns the Class corresponding to the type boolean.
TYPE Field for Primitive Type Wrappers: The .class syntax is a more convenient and the preferred way to obtain the Class for a primitive type; however there is another way to acquire the Class. Each of the primitive types and void has a wrapper class in java.lang that is used for boxing of primitive types to reference types. Each wrapper class contains a field named TYPE which is equal to the Class for the primitive type being wrapped.
Class c = Double.TYPE;
There is a class java.lang.Double which is used to wrap the primitive type double whenever an Object is required. The value of Double.TYPE is identical to that of double.class.
Methods that Return Classes: There are several Reflection APIs which return classes but these may only be accessed if a Class has already been obtained either directly or indirectly.
Class.getSuperclass()
Returns the super class for the given class.
Class c = javax.swing.JButton.class.getSuperclass();
The super class of javax.swing.JButton is javax.swing.AbstractButton.
Class.getClasses()
Returns all the public classes, interfaces, and enums that are members of the class including inherited members.
Class[] c = Character.class.getClasses();
Character contains two member classes Character.Subset and Character.UnicodeBlock.
Class.getDeclaredClasses()
Returns all of the classes interfaces, and enums that are explicitly declared in this class.
Class[] c = Character.class.getDeclaredClasses();
Character contains two public member classes Character.Subset and Character.UnicodeBlock and one private class Character.CharacterCache.
Class.getDeclaringClass() java.lang.reflect.Field.getDeclaringClass() java.lang.reflect.Method.getDeclaringClass() java.lang.reflect.Constructor.getDeclaringClass()
Returns the Class in which these members were declared. Anonymous Class Declarations will not have a declaring class but will have an enclosing class.
import java.lang.reflect.Field; Field f = System.class.getField("out"); Class c = f.getDeclaringClass();
The field out is declared in System.
public class MyClass { static Object o = new Object() { public void m() {} }; static Class<c> = o.getClass().getEnclosingClass(); }
The declaring class of the anonymous class defined by the object "o" is null.
Disadvantages
Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection.
- Performance Overhead
Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
- Security Restrictions
Reflection requires a run-time permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet.
- Exposure of Internals
Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code, breaks abstractions and therefore may change behavior with upgrades of the platform <ref>Disadvantages of Java Reflection API</ref>
C#
Key Features
It enables you to do simple things like: Check the type of an object at runtime (simple calls to typeof() for example) Inspect the Attributes of an object at runtime to change the behavior of a method (the various serialization methods in .NET) To much more complicated tasks like: Loading an assembly at runtime, finding a specific class, determining if it matches a given Interface, and invoking certain members dynamically.
Advantages
- Signature Based Polymorphism
C# programmers are familiar with polymorphism based on interface inheritance. Reflection provides an alternative where we can invoke methods having same signature, from different classes not having a common interface.
- Inspecting and Manipulating Classes
If we need to write code that depends on class details known only at run time, then reflection comes as an easy way to proceed.
- Creating Adaptable and Flexible Solutions
It is possible to write code for factory design pattern by loading classes using reflection instead of writing fixed code depending on specific static types with if-else statements inside the factory method.
Example:
To write a C# .Net program which uses reflection, the program should use the namespace System.Reflection. To get type of the object, the typeof operator can be used. There is one more method GetType() which also can be used for retrieving the type information of a class. The Operator "typeof" allows us to get class name of our object and GetType() method is used to get data about object's type. Suppose we have following class:
public class TestDataType { public TestDataType() { counter = 1; } public TestDataType(int c) { counter = c; } private int counter; public int Inc() { return counter++; } public int Dec() { return counter--; } }
At first we should get type of object that was created. The following C# .Net code snippet shows how to do it <ref>C# Reflection</ref>
TestDataType testObject = new TestDataType(15); Type objectType = testObject.GetType();
Now objectType has all the required information about class TestDataType. We can check if our class is abstract or if it is a class. The System.Type contains a few properties to retrieve the type of the class: IsAbstract, IsClass. These functions return a Boolean value if the object is abstract or of class type. Also there are some methods that return information about constructors and methods that belong to the current type (class). It can be done in a way as it is done in next example:
Type objectType = testObject.GetType(); ConstructorInfo [] info = objectType.GetConstructors(); MethodInfo [] methods = objectType.GetMethods(); // get all the constructors Console.WriteLine("Constructors:"); foreach( ConstructorInfo cf in info ) { Console.WriteLine(cf); } Console.WriteLine(); // get all the methods Console.WriteLine("Methods:"); foreach( MethodInfo mf in methods ) { Console.WriteLine(mf); }
Now, the above program returns a list of methods and constructors of TestDataType class.
Disadvantages
- Exposes Implementation Details
Use of reflection exposes much of the implementation details such as the methods, fields, accessibility and other metadata of the class used.
- Performance
The code that is reflective is slow than the direct code that performs the same functionality. As reflection performance also depends on the kind of operations that are done in the code like creating objects, accessing members, making method calls, etc.
Smalltalk
Example in Smalltalk
w := Workspace new. w openLabel:'My Workspace' w inspect
Here we can inspect all the methods available to the instance 'w'.
PHP
Example in PHP
$reflector = new ReflectionClass("SimpleXMLElement"); echo $reflector;
Output of this example is the complete class map of the class SimpleXMLElement.
Comparison of Reflection in different languages
Java | Ruby | C# | PHP | C++ |
---|---|---|---|---|
Supports Reflection | Supports Reflection | Supports Reflection | Supports Reflection | Poor support for Reflection <ref>Tharaka Devadithya, Kenneth Chiu, Wei Lu, "Reflection for High Performance Problem Solving Environments", Computer Science Department, Indiana University, 2007</ref> |
Not Powerful and flexible as Ruby Reflection | Provides powerful and flexible Reflection mechanism | Not Powerful and flexible as Ruby | Powerful and flexible | Provides RTTI support which provides only a very restricted subset of reflection |
Uses Reflection | Ability to introspect as it is a dynamic language | Uses Reflection | Ability to type introspect as it is a dynamic language | C++ supports type introspection via the typeid and dynamic_cast keywords |
Variable's type determines its class and methods. | Ruby supports liberated objects(cannot tell exactly what an object can do until you look under its hood) | Variable's type determines its class and methods. | Uses Reflection class | It is possible to get object run-time type only if object class contains virtual functions(using RTTI) |
Java Reflection API (is a bit higher level than the C# Reflection API) <ref>Difference between Java and C# Reflection APIs</ref> | Ruby has a rich set of Reflection APIs | Has Reflection APIs | Has Reflection APIs | Has no Reflection APIs |
Applications of Reflection
- Reflection has become invaluable to programmers who need to connect code with data. For example in a GUI environment, a button might need to invoke different methods in different classes. Reflection can be used here to call the method on any given class.
- Programmers who deal with a multitude of classes at the same time can use reflection to create a serializer that for a given class uses reflection to go through all the instance variables and processes them accordingly.
- Reflection is used in large test frameworks where reflection helps in identifying the test methods for different scenarios.
- Reflection provides the ability to morph the code based on dynamic situations. This provides a sense of artificial intelligence to the program as whole.
- Reflection can be used to debug and verify code as it provides access to the insides of a program.
- Reflection is very useful when the software is upgraded regularly. It provides an easy method to check for available methods and classes. This prevents the errors caused by the absence of methods and classes when they are deprecated.
Advantages and disadvantages of reflection
Advantages
- Extensibility: Reflection provides the capability of using external and user defined classes by instantiation of extensibility objects using their fully qualified names.
- Class browsers in IDEs: The ability to examine the members of classes makes implementation of visual aids , auto-completion and documentation easy in development tools for programmers.
- Debugging: Reflection allows the user to observe the private members in classes. This capability can be used to debug classes and their interactions.
- Test Harness: Reflection can be used to call a set of testing APIs defined on a class for maximum coverage of testing.
- Correctness : Reflection improves the robustness and the correctness of a program especially in dynamically typed languages as run time checks can be added to check the availability of the methods or classes.
Disadvantages
- Reflection introduces lot of performance overhead when compared to non-reflective code. Hence it should be used judiciously.
- Since it provides access to the internals of a class or an encapsulated object security becomes a major issue.
- Since it is run-time binding we lose the security of compile time checks and verification <ref>Analysis of Programming Languages</ref>
Conclusion
This article makes an attempt to explain the concept of Reflection in Object Oriented Programming. The article mentions the different approaches to reflection in Ruby and other languages.It mentions the usage of Reflections and the advantages and disadvantages of using Reflection. A follow up to this article would be to study the concept of Metaprogramming.
References
<references />