编程中的反射_Reflection in programming

反射的介绍

反射是指一种特定类型的计算机程序:能够在运行时,以一种依赖于它的代码的抽象特性,而更改它的运行时(Run time)行为的特性.用比喻来说,那种程式能够“观察”并且修改自己的行为.

最早的计算机在它们的原生汇编语言里编程,它本质上是反射,因为它是由定义编程指令作为数据.反射功能,如修改指令或分析它们是很平常的.编程迁移到更高层次的语言如C,这种实践消失了,直到带有反射特性的编程语言在它们的类型系统中出现.

Brian Cantwell Smith在1982年的博士论文中介绍了编程语言的计算反射的这种概念,并且在meta-circular解释器的概念中用作Lisp的一个组成部分.

反射可以用于观察和/或修改程序在运行时的执行.一个reflection-oriented程序组件可以监测一个范围内的代码执行情况,可以根据期望的目标与此相关的范围修改本身.这通常是通过在运行时动态分配程序代码实现.

在面向对象的编程语言如Java中,反射允许在编译期间不知道接口的名称,字段、方法的情况下在运行时检查类、接口、字段和方法.它还允许的实例化新对象和调用的方法.

反射还可以用来动态地适应给定的程序在不同情况。例如,考虑一个应用程序,它使用两个不同的类X和Y互相交替执行类似的操作.没有 reflection-oriented编程,应用程序可能是硬编码的,以调用方法名称的类X和类Y.然而,使用reflection-oriented 编程范式中,应用程序可以在没有硬编码方法名称情况下利用反射设计和编写调用类中的方法X和Y.Reflection-oriented编程几乎总是需要 更多的知识,框架,关系映射和对象关联,以利用更通用的代码执行.reflection-oriented编程的使用可以在某种程度上避免硬编码.

反射经常作为软件测试的一部分,比如运行时创建/实例化模拟对象.

反射也是元编程的一个关键策略.

一个语言支持反射提供在运行时可用的许多功能,否则其只会在令人费解的较低级别的语言完成.以上的这些特征的能力是:

  • 发现并修改源代码的结构(如代码块、类、方法、协议等)作为一个第一型的运行时对象.
  • 转换一个字符串来匹配一个class或者function的符号以进入一个引用或者来调用这个类或函数.
  • 计算一个字符串,就好像它是一个在运行时源代码语句.
  • 创建一个新的语言字节码解释器来给编程构造一个新的意义或用途.
    这些特性可以用不同的方法实现.

编译语言依赖于他们的运行时系统提供有关源代码的信息.一个objective-c编译的可执行文件,例如,记录所有方法的名字在一块可执行文件, 提供一个表来对应这些与底层的方法(或这些方法的选择器)编译进程序.在编译语言,支持运行时创建的功能,例如Common Lisp,运行时环境必须包括一个编译器或解释器.

反射可以为没有内置的反射工具的语言实现,其通过使用一个程序转换系统来定义自动的源代码变更.

反射在语言中的实现

首先在java中,反射是AOP实现的关键,其允许获取并修改类的内部结构和方法:

import java.lang.reflect.InvocationTargetException;

public class ReflectTester {

public static void main(String[] args) throws ClassNotFoundException, IllegalArgumentException, SecurityException,
IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException {
// Without reflection
new Foo().hello(“Jim”);

// With reflection
Class<?> clazz = null;
clazz = Class.forName(“Foo”);
clazz.getMethod(“hello”,String.class).invoke(clazz.newInstance(),”Lee”);
}
}

class Foo {
private String name;

public Foo() {
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public void hello(String name) {
System.out.println(“Hello “ + name);
}
}

在python中通过globals()方法来实现反射机制,其将字符参数转化为对象实例:

>>> class obj:
def init(self, str):
print str

>>> var = ‘obj’
>>> instance = globals()[var]
>>> instance
<class main.obj at 0x00B1F0A0>

同样在javascript中也提供反射机制:

如在对象中遍历获取一个属性及其值

for (var member in object) {
alert(‘Name: ‘ + member);
alert(‘Value: ‘ + object[member]);
}

evel函数同样可以用来将string以函数方式执行:

// Without reflection
new Foo().hello()

// With reflection
// assuming that Foo resides in this
new this‘Foo’‘hello’

// or without assumption
new (eval(‘Foo’))()‘hello’

// or simply
eval(‘new Foo().hello()’)

资源:

http://en.wikipedia.org/wiki/Reflection_(computer_programming)