编程学习biancheng.45soft.com 本站提供了各种在线教程和资料,供大家学习与参考.
编程学习
当前位置: 主页 > Perl > 绑定变量 >

Perl 绑定变量


有些人类的工作需要伪装起来。有时候伪装的目的是欺骗,但更多的时候,伪装的目的是为了在更深层次做一些真实的通讯。比如,许多面试官希望你能穿西服打领带以表示你对工作是认真的,即使你们俩都知道你可能在工作的时候永远不会打领带。你思考这件事的时候可能会觉得很奇怪:在你脖子上系一块布会神奇地帮你找到工作。在 Perl 文化里, tie 操作符起到类似的作用的角色:它让你创建一个看起来象普通变量的变量,但是在变量的伪装后面,它实际上是一个羽翼丰满的 Perl 对象,而且此对象有着自己有趣的个性。


它只是一个让人有点奇怪的小魔术,就好象从一个帽子里弹出一个邦尼兔那样。(译注:英文 tie 做动词有"捆绑"之意,而做名词有"领带"之意.)用另外一个方法来看,在变量名前面的趣味字符 $,@,%,或者 * 告诉 Perl 和它的程序许多事情——他们每个都暗示了一个特殊范畴的原形特性。你可以利用 tie 用各种方法封装那些特性,方法是用一个实现一套新性质的类与该变量关联起来。


比如,你可以创建一个普通的 Perl 散列,然后把它 tie (绑)到到一个类上,这个类把这个散列放到一个数据库里,所以当你从散列读取数据的时候,Perl 魔术般地从一个外部数据库文件抓取数据,而当你设置散列中的数值的时候,Perl 又神奇地把数据存储到外部数据库文件里。这里的"魔术","神奇"指的是“透明地处理一些非常复杂的任务”。你应该听过那些老话:再先进的技术也和 Perl 脚本没什么区别。(严肃地说,那些在 Perl 内部工作的人们把魔术(magic)一词当作一个技术术语,特指任何附加在变量上的额外的语义,比如 %ENV 或者 %SIG。捆绑变量只是其中一种扩展。)


Perl 已经有内建的 dbmopen 和 dbmclose 函数,它们可以完成把散列变量和数据库系在一起的魔术,不过那些函数的实现是早在 Perl 没有 tie 的时候。现在 tie 提供了更通用的机制。实际上, Perl 本身就是以 tie 的机制来实现 dbmopen 和 dbmclose 的。


你可以把一个标量,数组,散列或者文件句柄(通过它的类型团)系到任意一个类上,这个类提供合适的命名方法以截获和模拟对这些对象的正常访问。那些方法的第一个是在进行 tie 动作本身时调用的:使用一个变量总是调用一个构造器,如果这个构造器成功运行,则返回一个对象,而 Perl 把这个对象藏在一个你看不见的地方——在“普通”变量的深层内部。你总是可以稍后用 tied 函数在该普通变量上检索该对象:

tie VARIABLE, CLASSNAME, LIST;   # 把VARIABLE 绑定到 CLASSNAME
$object = tied VARIABLE;

上面两行等效于:

$object = tie VARIABLE, CLASSNAME, LIST;

一旦该变量被捆绑,你就可以按照平时那样对待该普通变量,不过每次访问都自动调用下层对象的方法;所有该类的复杂性都隐藏在那些方法调用的背后。如果稍后你想打破变量和类之间的关联,你可以 untie (松绑)那个变量:

untie VARIABLE;

你几乎完全可以把 tie 看作一种有趣的 bless 类型,只不过它是给一个光秃秃的变量赐福,而不是给一个对象引用赐福。它同样还可以接收额外的参数,就象构造器那样——这个恐怕也不新鲜了,因为它实际上就是在内部调用一个构造器,该构造器的名字取决于你尝试的变量类型:是 TIESCALAR,TIEARRAY,TIEHASH,或者TIEHANDLE。(注:因为这些构造器是独立的名字,你甚至可以提供一个独立的类来实现它们。那样,你就可以把标量,数组,散列,和文件句柄统统绑定到同一个类上,不过通常不是这么干的,因为它会令其他的魔术方法比较难写。)调用这些构造器的时候,它们用所声明的 CLASSNAME 为它们的调用者作为类方法调用,另外把你放在 LIST 里的任何东西作为附加的参数。(VARIABLE 并不传递给构造器。)


这四种构造器每种都返回一个普通风格的对象。它们并不在乎它们是否从 tie 里调用的,类里的其他方法也不在意,因为如果你喜欢的话你总是可以直接调用它们。从某种意义来说,所有魔术都是在 tie 里,而不是在实现 tie 的类里。该类只是一个有着有趣的方法名的普通类。(实际上,有些捆绑的模块提供了额外的一些方法,这些方法是不能通过捆绑的变量看到的;你必须明确调用这些方法,就象你对待其他对象方法一样。这样的额外方法可以提供类似文件锁,事务保护,或者任何其他实例方法可以做的东西。)


因此这些构造器就象其他构造器那样 bless(赐福)并且返回一个对象引用。该引用不需要指向和被捆绑的变量相同类型的变量;它只是必须被赐福,所以该绑定的变量可以很容易在你的类中找到支持。比如,我们的长例子 TIEARRAY 就会用一个基于散列的对象,这样它就可以比较容易地保存它在模拟的数组的附加信息。


tie 函数不会为你 use 或者 require 一个模块——如果必要的话,在调用 tie前你必须自己明确地做那件事。(另外,为了保持向下兼容,dbmopen 函数会尝试 use 一个或者某个 DBM 实现。但你可以用一个明确的 use 修改它的选择优先级——只要你 use 的模块是在 dbmopen 的模块列表中的一个。参阅 AnyDBM?_File 模块的在线文档获取更完善的解释。)


一个捆绑了的变量调用的方法有一个类似 FETCH 和 STORE 这样的预定义好了的名字,因为它们是在 Perl 内部隐含调用的(也就是说,由特定事件触发)。这些名字都在 ALLCAPS,内部隐含调用的(也就是说,有特定事件触发)。这些名字都是全部大写,这是我们遵循的一个称呼这些隐含调用过程的习惯。(其他遵循这种传统的习惯有 BEGIN,CHECK,INIT, END,DESTROY, 和 AUTOLOAD,更不用说 UNIVERSAL->VERSION。实际上,几乎所有 Perl Perl 预定义的变量和文件句柄都是大写的:STDIN,SUUPER,CORE,CORE::GLOBAL,DATA, @EXPORT,@INC,@ISA,@ARGV 和 %ENV。当然,内建操作符和用法是另外一个极端,它们没有用大写的。)


我们首先要介绍的内容很简单:如何捆绑一个标量变量。

Perl
Perl 绑定变量