首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >反射到底是什么,什么时候是好的方法?

反射到底是什么,什么时候是好的方法?
EN

Stack Overflow用户
提问于 2009-05-14 16:22:03
回答 9查看 4.3K关注 0票数 19

反射到底是什么?我读过Wikipedia上关于这个主题的文章,我理解它是一种元编程,程序可以在运行时自我修改,但这意味着什么?在哪种情况下,这是一种好的方法,什么时候使用它是最好的?

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2009-05-14 16:26:03

反射是一种工具,您可以在运行时查询对象的属性。例如,Python、Java和.Net都提供了一些工具,您可以在其中查找对象的实例变量或方法。

O/R映射层就是反射应用程序的一个例子。有些使用反射来构造对象,方法是在运行时查询对象的属性并动态填充实例。这允许您基于某种数据字典中的元数据以编程方式执行此操作,而不必重新编译应用程序。

举一个简单的例子,我将使用Python,因为它的反射功能使用起来非常简单,并且比java或.Net涉及的样板更少。

代码语言:javascript
复制
ActivePython 2.5.2.2 (ActiveState Software Inc.) based on
Python 2.5.2 (r252:60911, Mar 27 2008, 17:57:18) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class foo:
...     def __init__(self):
...             self.x = 1
...
>>> xx = foo()      # Creates an object and runs the constructor
>>> xx.__dict__     # System metadata about the object
{'x': 1}
>>> a = xx.__dict__ # Now we manipulate the object through 
>>> a['y'] = 2      # its metadata ...
>>> print xx.y      # ... and suddenly it has a new instance variable
2                   
>>>

现在,我们已经使用基本反射来检查任意对象的实例变量。Python上的特殊变量__dict__是一个对象的系统属性,该对象有一个哈希表,其中的成员以变量(或方法)名称为关键字。我们对对象进行了反射检查,并使用反射工具人为地将第二个实例变量插入到该对象中,然后我们可以通过将其作为实例变量调用来显示该变量。

注意,这个特殊的技巧在Java或.Net上不起作用,因为实例变量是固定的。这些语言的类型系统不允许像python的“鸭子”类型系统那样在运行时添加新的实例变量。但是,您可以反射性地更新在类型定义中声明的实例变量的值。

您还可以使用反射动态构造方法调用,并执行各种其他巧妙的技巧,例如基于参数实例化对象。例如,如果你有一些基于插件的系统,其中某些功能是可选的,你可以使用反射来查询插件,了解它提供了什么服务(可能通过查询是否实现了某些接口),而不需要显式的元数据。

许多动态语言接口(如OLE自动化)都使用反射作为接口的组成部分。

票数 26
EN

Stack Overflow用户

发布于 2009-05-14 16:26:14

我能想到的第一个好例子是,当您需要在给定对象上执行一组方法时,而不知道在编译时将在其中存在哪些方法。

以单元测试框架为例。负责运行所有单元测试的test runner类并不提前知道您要为方法命名什么。它所知道的就是它们将以"test“为前缀(或者在Java5的情况下,使用@Test注释)。因此,当给定一个测试类时,它会对该类进行反射,以便获得其中所有方法的列表。然后,它将这些方法名作为字符串进行迭代,如果这些方法以"test“开头,则在对象上调用这些方法。如果没有反思,这是不可能的。这只是一个例子。

票数 3
EN

Stack Overflow用户

发布于 2009-05-14 16:28:52

至少在我能想到的一个项目中,反射对我很有用。我们编写了一个内部“流程管理器”程序,该程序以一定的时间间隔执行许多关键业务流程。该项目的设置使得核心实际上只是一个带有timer对象的windows服务,这些timer对象大约每30秒触发一次,并检查要做的工作。

实际工作是在一个类库(适当地称为"WorkerLib")中完成的。我们使用执行某些任务(移动文件、上传数据到远程站点等)的公共方法来定义类。这个想法是,核心服务可以从worker库调用方法,而不需要知道它调用的方法的任何信息。这允许我们在数据库中为作业创建一个调度,甚至在不改变核心系统的情况下将新方法添加到类库中。

基本思想是,我们可以在核心服务中使用反射来执行方法,这些方法的名称已经存储在数据库中,定义了调度。它在实践中相当整洁。我们的核心服务是可靠的,可以根据需要处理作业的执行,而实际的worker库可以根据需要进行扩展和更改,而不需要核心甚至关心。

如果您需要进一步的解释,请随时询问。这是我能想到的最好的方式来解释一个真实世界的场景,在这个场景中,反射确实让我们的事情变得更容易。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/864332

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档