Introduction to Object Oriented Programming, 3rd Ed

Timothy A. Budd

Chapter 25

Reflection and Introspection

Outline

  1. Roadmap
  2. Class Objects
    1. Things you can do with a Class Object
    2. Getting the Class from a String
    3. Testing if an Object is an Instance of a Class
  3. Methods as Objects
    1. Using a Method
    2. Dynamic Execution
  4. Class Loading
  5. Metaclasses -- Strange Loops
    1. Rational for MetaClasses
  6. Relation to Components

Other Material

Intro OOP, Chapter 25, Outline

Roadmap

Reflection and Introspection imply a program that can dynamically learn about or modify itself. Not all abilities are found in all languages. Some languages do not have any support for reflection or introspection.
Intro OOP, Chapter 25, Slide 01

Class Objects

In most languages, introspection begins with an object that represents the class. Typically this object has class Class.

Intro OOP, Chapter 25, Slide 02

Things you can do with a Class Variable

One operation that can be performed with a value of type class is to get its parent class
	Class parentClass = aClass.getSuperclass(); // Java
Another operation is to get the list of all subclasses for a class.
	aSet <- aClass subclasses  " Smalltalk "
You can also get the name of the class as a string
	char * name = typeinfo(aVariable).name();  // C++
Intro OOP, Chapter 25, Slide 03

Getting the Class from a String

In some languages, you can take the name of a class (a string) and from this get the class object.
	Class aClass = Class.forName("classname"); // Java
The class does not even have to be loaded. The class will automatically be loaded for you.
Intro OOP, Chapter 25, Slide 04

Testing if an Object is an Instance of a Class

We have seen already that most languages provide a way to test if an object is an instance of a class
	if Member(aVariable, Child) then
		aChild = Child(aVariable)   (* Object Pascal *)
This is needed for downcasting.

However, if you find yourself using this a lot, then you aren't thinking in an object-oriented way, since often such situations can be better written using polymorphism.

Intro OOP, Chapter 25, Slide 05

Methods as Objects

The next level of complexity is treating a method as an object.

First step is to get a collection of methods from a class

	Method [ ] methods = aClass.getDeclaredMethods();  // Java

	aSet <- aClass selectors.   // Smalltalk

Intro OOP, Chapter 25, Slide 06

Using a Method

What can you do with a method object? You can do the usual things of getting its names, argument type signatures, so on.
	System.out.println(methods[0].getName());
	Class c = methods[0].getReturnType();
Intro OOP, Chapter 25, Slide 07

Dynamic Execution

You can also invoke the method, passing it the receiver and an array of arguments:
	Class sc = String.class;
	Class [ ] paramTypes = new Class[1];
	paramTypes[0] = sc;
	try {
		Method mt = sc.getMethod("concat", paramTypes);
		Object mtArgs [ ] = { "xyz" };
		Object result = mt.invoke("abc", mtArgs);
		System.out.println("result is " + result);
	} catch (Exception e) {
		System.out.println("Exception " + e);
	}
Here we dynamically look up a method, based both on name and type signature, then create an array of arguments, then execute the method.
Intro OOP, Chapter 25, Slide 08

Class Loading

Java has a class named ClassLoader that allows you to define a class from an array of bytes:
class SimpleClassLoader extends ClassLoader {
	public Class getClass (String name) {
		Class theClass = null;
		try {
			File f = new File(name);
			InputStream is = new FileInputStream(f);
			int bufsize = (int) f.length();
			byte buf [] = new byte[bufsize];
			is.read(buf, 0, bufsize);
			is.close();
			theClass = defineClass (null, buf, 0, buf.length);
		} catch (Exception e) {
			System.err.println("Error during load " + e);
			System.exit(1);
		}
		return theClass;
	}
}
Once you have a class, you can create instances, or execute methods.
Intro OOP, Chapter 25, Slide 09

Metaclasses -- Strange Loops

You can get into some interesting places by asking the right questions. In Java this path circles back on itself very quickly; Class is an intance of itself.

In Smalltalk, the path goes on a bit longer before it circles back on itself.

Intro OOP, Chapter 25, Slide 10

Rational for Metaclasses

Remember that by introducing new classes that represent classes, Smalltalk was able to solve the following problem The answer was, you don't. You add a new child class that defines the behavior you want, and put this between the object and the true parent.
Intro OOP, Chapter 25, Slide 11

Relationship to Components

Relection and Introspection have taken on increasing importance as the field moves from object-based computing to component-based computing (COM, Corba, JavaBeans, etc).

This is because components must often be dynamically loaded and executed. And reflection is the underlying mechanism that permits this.

Intro OOP, Chapter 25, Slide 12