关于反射的用途是『降低模块间的耦合度』这个倒未必尽然

单就delphi来说,从实现上看,它的所谓反射是基于RTTI,而RTTI的出现按照官方的说法是为了实现RAD中窗体文件DFM的持久化而产生的,其实也不是针对DFM文件或TForm啦,由于TPersistent在声明的时候加上了{$M+},所以从TPersistent派生的对象都在编译的时候添加了RTTI,而在TComponent中又增加了对TReader和TWriter支持,说的准确一点、时髦一点RTTI是为了实现对象的持久化和反持久化,在Delphi3之后加入了接口,从而将COM引入,而在delphi6以后又加入了对接口的RTTI的支持,从而将SOAP也引入到了delphi之中,从这两个重大特性的加入上看到,除了Delphi对接口支持的越来越丰富,还有一点很重要的是Delphi很早就支持了远程方法调用RPC,对于RPC的支持并不是简单的对传输协议的支持,而是要在对象定义、编译层面对其实现的支持。尽管COM的RPC与SOAP的RPC在表象上是有所不同的,但我们其实可以断定,在Delphi6之后已经就可以对对象的方法动态调用了。事实上也确实如此,一切奥秘尽包含在TypInfo,IntfInfo,ObjAuto,Invoker这些单元之中,只可惜在Help中并没有体现。我记得李维发过这样一句叹息,说其实在Borland实验室中十年前就有很多天才很多很Cool的想法但是得不到老板的支持,最后只得痛惜离开Borland。我在翻看VCL代码的时候,相信这确实是真的,现在很多在.NET或Java上很时髦的特性,有多少是Delphi在语言层面上是不支持的呢,我们忽略了Delphi是因为它们还没有来得及被Borland的工程师推向前台、还没来得及将其做成框架发布出来,而这些工程师就被赶跑了。

  可能是误会了反射的意思,这里并不是指对另外单元中声明的引用,而是指在运行时可以获得代码的特性以及在运行时可以改变它的行为。这样说可能抽象一点,说的稍微形象一点,一般编译型语言中,程序中所有定义的变量和函数,它们是否被使用、如何被使用,都是要在编码的时候设定好全部的执行逻辑的,而运行时只是遵循其中一条或几条执行路径执行的,而所谓的反射就是要能够在运行时通过一个外部的控制来决定程序内部的执行行为,也就是说从逻辑上看,程序不再是一个闭包的逻辑系统,而可以依赖于外部的注入。简单的说程序的运行时结构是由许多代码段、堆和栈这三种内存块组成,而所谓的执行就是指内部逻辑可以访问到代码段中的所有定义,将函数代码放在栈上展开执行,在堆中间分配所需空间以及一些其他的诸如IO访问等行为的集合。所以,如果要实现外部的控制注入,即反射,至少需要满足能够访问类似代码段上数据而获得变量和函数定义的部分,其次还要能够控制函数在栈上展开执行。

Delphi这种基于RTTI信息而实现的反射和Java、.Net有显著的不同。由于Java、.Net是先将程序编译成bytecode或CIL,在将中间代码让VM来执行,所以在这一类语言上实现反射的基本方式是获得bytecode和CIL,这部分内容就类似于代码段上的信息,然后外部注入的逻辑被重新编译生成新的中间代码后再让VM执行,从而产生新的行为。在这种机制下,非但可以实现反射,而且还可以对中间代码实行反编译而获得原始代码。而Delphi对反射的实现和Java以及.Net有本质的不同,它将对象的字段和函数的信息编译进RTTI,在编码的时候将对象注册进一个全局的列表中,运行时通过访问该列表而获得所需的对象,再从对象的RTTI中获得字段和函数的信息,同时提供出一种可以在运行时执行对象方法的函数,也不需要再编译,于是就间接的实现了反射机制。但是我们也应该注意到Delphi的反射和Java相比,首先是并不能反射到所有的变量和函数,例如全局的函数,静态变量就不会获得,其次由于不存在中间代码,也不存在反编译的问题,当然,这些都不是重点。其实这些东西在Delphi6\7的时候就已经有了,因为要支持SOAP,在SOAP标准中有一个SOAP的RPC表示,也就是说SOAP在调用远程对象方法的时候,也就是通过字符串来驱动的,所以不但有对象的RTTI,也可以在声明接口的 时候添加{$M+}来编译进接口的RTTI,从而对接口方法也可以使用字符串来驱动。又因为最初的设计是针对SOAP的,所以在ObjAuto单元中ObjectInvoke方法不支持对象类型和指针类型,毕竟SOAP在远程调用方法时传物理地址是没有意义的,当然,Variant也是不支持对象类型的。

delphi 反射(原理)的更多相关文章

  1. Delphi反射

    最近在写一个框架,需要用到反射,与C# java这些原生支持反射的语言不同,delphi对反射的支持相对要弱一些,但也够用了,其实C#的大部分的思想还是从 delphi而来,毕竟都是安德鲁斯的杰作. ...

  2. Lua刚開始学习的人(一)--Lua 简单教学

    近期因为工作原因.临时木有<Oracle起步学习>续集.领导知道学习下Lua脚本语言.看了一周了.趁热打铁,留下点实用的东西吧. 本系列会主要针对宿主语言为 Delphi,原理都是一样的, ...

  3. Django 的 cbv

    Django 的 cbv 正如我们了解到的,Django 写视图函数有两种写法:cbv 和 fbv.cbv 提倡使用类来写,fbv 使用函数来 写.当然为了代码的重复行,官方更推荐使用 cbv. 写 ...

  4. Shaderlab-10chapter-立方体纹理、玻璃效果

    10.1.1天空盒子 window - Lighting - skyMaterial 创建mat,shader选自带的6 side shader 确保相机选skybox 如果某个相机需要覆盖,添加sk ...

  5. IoC原理-使用反射/Emit来实现一个最简单的IoC容器

    从Unity到Spring.Net,到Ninject,几年来陆陆续续用过几个IoC框架.虽然会用,但也没有一直仔细的研究过IoC实现的过程.最近花了点时间,下了Ninject的源码,研究了一番,颇有收 ...

  6. Java反射机制及IoC原理

    一. 反射机制概念 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义.在java中,只要给定类的名字, 那么就可以通 ...

  7. Android反射机制实现与原理

    本文介绍Android反射机制实现与原理,在介绍之前,要和Java进行比较,所以先看下Java中的反射相关知识: 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或 ...

  8. JAVA的反射机制原理

    http://www.cnblogs.com/hongxinlaoking/p/4684652.html 一  反射机制的概念: 指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于 ...

  9. 【JAVA - 基础】之反射的原理与应用

    一.反射简介 反射机制指的是程序在运行时能够获取自身的信息.在JAVA中,只要给定类的名字,那么就可以通过反射机制来获取类的所有信息. 1.反射的应用 JDBC编程中的:Class.forName(& ...

随机推荐

  1. 如何找到Linux下常用命令的源码

    Linux系统,常用命令的来源很多,有些命令是shell自带的,比如cd,通过执行help命令,可以查看当前系统所有的内置命令. 用type <cmd_name>来查看一个命令是否为内置命 ...

  2. 一个疑惑的的问题-ntvdm.exe进程

    今天测试反馈了一个问题,在启动我们程序某个模块的程序时,会立即出现一个ntvdm.exe进程,此进程会占用大量的系统资源,导致系统卡住. 当第一眼看到这个现象时,以为是电脑中毒了,所以立即在网上查. ...

  3. Poj 2586 / OpenJudge 2586 Y2K Accounting Bug

    1.Link: http://poj.org/problem?id=2586 2.Content: Y2K Accounting Bug Time Limit: 1000MS   Memory Lim ...

  4. Linux RedHat无法安装软件问题(No package gcc available. Nothing to do)

    在一个新的Linux服务器上安装nginx的时候,命令都不能解析,缺少gcc编辑器,安装gcc的命令也出错. [root@localhost ~]# yum -y install gcc Loaded ...

  5. 按照自己的理解实现比特交换协议(alternating-bit protocol)

    一开始的思路是想写两个程序的,发送端和接收端.但是后来想了下,因为是模拟的,所以不用这么麻烦,直接自己定制场景(比如说丢包阿,包出错阿,超时之类的). 基本上是根据上图所写的,一个函数发包,一个函数接 ...

  6. CentOs7&zookeeper

    下载安装包 wget http://www.apache.dataguru.cn/zookeeper/stable/zookeeper-3.4.6.tar.gz 解压 tar xzvf zookeep ...

  7. Excel数据复制到Winform控件ListView

    先给窗体添加一个右键菜单contextMenuStrip 加一个下拉项[粘贴] 粘贴事件: private void tsmiPaste_Click(object sender, EventArgs ...

  8. 图片延迟加载库Layzr

    <!DOCTYPE html> <html> <head> <title>Layzr Demo</title> <script src ...

  9. Spark Streaming揭秘 Day32 WAL框架及实现

    Spark Streaming揭秘 Day32 WAL框架及实现 今天会聚焦于SparkStreaming中非常重要的数据安全机制WAL(预写日志). 设计要点 从本质点说,WAL框架是一个存储系统, ...

  10. 为cocos2d-x实现安卓输入框。非全屏,无dialog,绑定到lua

    cocos2d-x官方自带的输入框,简直惨不忍睹,在ios还好,在安卓简直了..用过的都知道... 所以为了用户体验,我们自己搞一个吧.输入框这种东西比较特殊,不像按钮.列表框之类的很容易实现,因为涉 ...