自省与反射的简单认识
第一次听说这两个概念,是在 Thinking in Java (4th Edition) 中的,而深入学习他们则是在 Python 语言的学习中,以下我用 Python 来举例说明。
wikipedia: In computer science, reflection is the ability of a computer program to examine and modify its own structure and behavior (specifically the values, meta-data, properties and functions) at runtime.
反射(Reflection) 是指计算机程序可以在运行时动态监测并修改它自己的结构和行为,比如值、元数据、属性和函数等的能力。通过反射,可以在运行时动态监测、生成、修改自己实际执行的等效代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class HelloClass(object): def __init__(self, method): self.method = method print('You are calling me from ' + self.method) def say_hello(self): print("Hello -- From: " + self.method) print() # Normal obj = HelloClass('Normal') obj.say_hello() # Reflection class_name = "HelloClass" method = "say_hello" obj = globals()[class_name]('Reflection') getattr(obj, method)() |
1 2 3 4 5 6 |
You are calling me from Normal Hello -- From: Normal () You are calling me from Reflection Hello -- From: Reflection () |
两种方法可以达到同样的效果。但是,第一种方法是我们所说的常规方法,创建 HelloClass 这个 class 的一个实例,然后调用其中的方法。第二种我们用到了反射机制,通过 globals()
这个字典中来查找 HelloClass
这个类,并加以参数进行实例化于 obj
,之后通过 getattr
函数获得 say_hello
方法,传参调用。
反射的好处在于,class_name
和 method
变量的值可以在运行时获取或者修改,这样可以动态地改变程序的行为。
wikipedia: In computing, type introspection is the ability of a program to examine the type or properties of an object at runtime.
自省(Introspection) 是程序在运行时检测自己的某个对象的类型或者属性、方法的能力。例如在 Python 中的 dir
方法。
1 2 3 4 5 6 7 8 9 10 11 |
class HelloClass(object): def __init__(self, method): self.method = method print('You are calling me from ' + self.method) def say_hello(self): print("Hello -- From: " + self.method) print() obj = HelloClass('Normal') obj_msg = dir(obj) for x in obj_msg: print (x) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
__class__ __delattr__ __dict__ __doc__ __format__ __getattribute__ __hash__ __init__ __module__ __new__ __reduce__ __reduce_ex__ __repr__ __setattr__ __sizeof__ __str__ __subclasshook__ __weakref__ method say_hello |
通过 dir()
函数从而做到自省,它可以返回某个对象的所有属性、方法等列表。
通过上述简单描述,我们大概知道了反射其实是包含着自省能力的,不仅可以获取到对象的各种属性信息,而且还可以动态修改自身的结构和行为。
objc_class 结构
在 ObjC 中,也支持在运行时检查对象类型这一操作,并且这个特性是内置于 Foundation 框架的 NSObject 协议中的。凡是公共基类(Common Root Class),即 NSObject 或 NSProxy ,继承而来的对象都要遵循此协议。
虽然 ObjC 支持自省这一特性,就一定会对 Class 信息做存储。这里我们便要引出 isa 指针。倘若对 ObjC 有一定的学习基础,都会知道 Objective-C 对象都可以通过 clang 进行 c 的语法格式转换,从而以 struct 来描述。所有的对象中都有一个 isa
指针,其含义是: it is a object! 而在最新的 runtime 库中,其 isa 指针的结构已经发生了变化。
以下代码均参考 runtime 版本为 objc4-680.tar.gz。
1 2 3 4 |
struct objc_object { private: isa_t isa; } |
会发现在 objc_object 这个基类中只有一个成员,即 isa_t 联合体(union) 类型的 isa 成员。而对于类对象的定义,可以从 objc_class 查看其结构:
第一次听说这两个概念,是在 Thinking in Java (4th Edition) 中的,而深入学习他们则是在 Python 语言的学习中,以下我用 Python 来举例说明。
wikipedia: In computer science, reflection is the ability of a computer program to examine and modify its own structure and behavior (specifically the values, meta-data, properties and functions) at runtime.
反射(Reflection) 是指计算机程序可以在运行时动态监测并修改它自己的结构和行为,比如值、元数据、属性和函数等的能力。通过反射,可以在运行时动态监测、生成、修改自己实际执行的等效代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class HelloClass(object): def __init__(self, method): self.method = method print('You are calling me from ' + self.method) def say_hello(self): print("Hello -- From: " + self.method) print() # Normal obj = HelloClass('Normal') obj.say_hello() # Reflection class_name = "HelloClass" method = "say_hello" obj = globals()[class_name]('Reflection') getattr(obj, method)() |
1 2 3 4 5 6 |
You are calling me from Normal Hello -- From: Normal () You are calling me from Reflection Hello -- From: Reflection () |
两种方法可以达到同样的效果。但是,第一种方法是我们所说的常规方法,创建 HelloClass 这个 class 的一个实例,然后调用其中的方法。第二种我们用到了反射机制,通过 globals()
这个字典中来查找 HelloClass
这个类,并加以参数进行实例化于 obj
,之后通过 getattr
函数获得 say_hello
方法,传参调用。
反射的好处在于,class_name
和 method
变量的值可以在运行时获取或者修改,这样可以动态地改变程序的行为。
wikipedia: In computing, type introspection is the ability of a program to examine the type or properties of an object at runtime.
自省(Introspection) 是程序在运行时检测自己的某个对象的类型或者属性、方法的能力。例如在 Python 中的 dir
方法。
1 2 3 4 5 6 7 8 9 10 11 |
class HelloClass(object): def __init__(self, method): self.method = method print('You are calling me from ' + self.method) def say_hello(self): print("Hello -- From: " + self.method) print() obj = HelloClass('Normal') obj_msg = dir(obj) for x in obj_msg: print (x) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
__class__ __delattr__ __dict__ __doc__ __format__ __getattribute__ __hash__ __init__ __module__ __new__ __reduce__ __reduce_ex__ __repr__ __setattr__ __sizeof__ __str__ __subclasshook__ __weakref__ method say_hello |
通过 dir()
函数从而做到自省,它可以返回某个对象的所有属性、方法等列表。
通过上述简单描述,我们大概知道了反射其实是包含着自省能力的,不仅可以获取到对象的各种属性信息,而且还可以动态修改自身的结构和行为。
objc_class 结构
在 ObjC 中,也支持在运行时检查对象类型这一操作,并且这个特性是内置于 Foundation 框架的 NSObject 协议中的。凡是公共基类(Common Root Class),即 NSObject 或 NSProxy ,继承而来的对象都要遵循此协议。
虽然 ObjC 支持自省这一特性,就一定会对 Class 信息做存储。这里我们便要引出 isa 指针。倘若对 ObjC 有一定的学习基础,都会知道 Objective-C 对象都可以通过 clang 进行 c 的语法格式转换,从而以 struct 来描述。所有的对象中都有一个 isa
指针,其含义是: it is a object! 而在最新的 runtime 库中,其 isa 指针的结构已经发生了变化。
以下代码均参考 runtime 版本为 objc4-680.tar.gz。
1 2 3 4 |
struct objc_object { private: isa_t isa; } |
会发现在 objc_object 这个基类中只有一个成员,即 isa_t 联合体(union) 类型的 isa 成员。而对于类对象的定义,可以从 objc_class 查看其结构: