Skip to content

Latest commit

 

History

History
139 lines (89 loc) · 5.69 KB

reflection.pod

File metadata and controls

139 lines (89 loc) · 5.69 KB

反射

反射(或称 内省)是运行期间向一个程序询问其自身情况的过程。即便你可以在不 使用反射的情况下编写不少有用的程序,一些诸如元编程(code_generation)等技术 从深刻了解系统中的实体获益良多。

Class::MOPclass_mop)简化了许多对象系统中的反射任务,但是很多有用的程序 并非彻底面向对象,很多程序也不会用到 Class::MOP。因为没有一个正规的系统,Perl 中存在着一些有效进行反射的惯用语(idioms)。

检查一个包是否存在

为检查一个包是否存在在系统之中────即,如果一段代码在某一点执行了一条带包名称的 package 指令────就是检查它是否从 UNIVERSAL 继承下来,这可以通过检查该包是 否能够执行 can() 方法来实现:

虽然你 可以 使用名为 0'' ……仅仅在你符号化地定义它们时,因为这些 并非 Perl 5 语法分析器禁止的标识符。 的包,can() 方法会在你将其作为调用 物时抛出一个方法调用异常。eval 代码块可以捕获这类异常。

你也 可以 对符号表的条目进行一一礼拜,但上述方法更加快速同时也更易理解。

检查一个类是否存在

由于 Perl 5 对包和类不加以严格区分,检查包存在性的技巧同时可用于检查一个类是否 存在。尚没有方法可以判断一个包是否是一个类。你 可以can() 来检查一个包 是否可以执行 new(),但这样无法保证任何找到的 new() 是方法,更不要说是构造 器了。

检查一个模块是否被加载

如果知道模块的名称,你可以通过查看 %INC 哈希来确定 Perl 是否相信它已经从 磁盘加载了这个模块。这个哈希和 @INC 是对应的;当 Perl 5 用 userequire 加载代码时,会在 %INC 中存储一个条目,其中键是欲加载模块的路径化名称,值是 模块完整的磁盘路径。就是说,加载 Modern::Perl 等效于:

路径的细节大部分取决于安装,但出于测试 Perl 是否成功加载一个模块目的,你可以把 模块名转换为正规文件形式并测试在 %INC 内是否存在:

没有什么阻止其它代码修改 %INC。按你偏执的程度,你可以自行检查路径和预期的包 内容,但是拥有充足利用修改此变量的模块(诸如 Test::MockObjectTest::MockModule) 可以这样做。修改 %INC 但理由不足的代码应该被替换。

检查模块的版本

无法保证某给定的模块是否提供版本号。即便如此,所有模块都继承自 UNIVERSALuniversal) ,因此它们全含有 VERSION() 方法以供调用:

如果给定的模块不覆盖 VERSION() 或不包含包变量 $VERSION,这个方法将返回一个未定义值。 类似地,如果该模块不存在,则对方法的调用将会失败。

检查一个函数是否存在

确定函数是否存在最简单的机制就是对包名使用 can() 方法:

除非 $pkg 是合法的调用物,否则 Perl 将会抛出异常;如果对其合法性有任何怀疑, 可以将此方法调用包装在一个 eval 块内。注意,若函数所在的包没有正确地覆盖 can(), 使用 AUTOLOAD()autoload)实现的函数可能会导致错误结果。这在其他包里便会 导致代码缺陷。

你可以用这个技巧决定一个模块的 import() 是否向当前名称空间导入某函数:

你也可以检查符号表和类型团来决定函数是否存在,但这种机制更简单也更好解释。

检查一个方法是否存在

没有检查某给定函数究竟是函数还是方法的通用办法。一些函数身兼双职,既是函数 也是方法,尽管听上去过于复杂并且同时是失误,但这确实是一个允许的特性。

搜查符号表

Perl 5 符号表是一个种类特别的哈希,其中的键是包全局符号的名称,值则是类型团。 类型团 是一种核心数据结构,它可以包含一个标量、一个数组、一个哈希、一个文 件句柄和一个函数。Perl 5 内部在查找这些变量时使用类型团。

通过在包名末尾添加双冒号,你可以将符号表当作哈希访问。例如,MonkeyGrinder 包 的符号表可以通过 %MonkeyGrinder:: 访问。

可以exists 操作符检查特定的符号名是否存在于符号表中(或随你喜好 修改符号表来 添加 或 or 删除 符号)。还应注意到一些对 Perl 5 核心的变更 已经修改了默认出现的类型团条目。特别是,Perl 5 早期版本总是为每个类型团默认提 供一个标量变量,现代化的 Perl 5 已经取消。

参见 perldoc perlmod 中的“Symbol Tables”小节以获取更多细节,最好采用不同于 本章介绍的反射技巧。

POD ERRORS

Hey! The above document had some coding errors, which are explained below:

Around line 5:

A non-empty Z<>

Around line 30:

Deleting unknown formatting code N<>