第九章 管理真实的程序(六) -UNIVERSAL包

UNIVERSAL包

Perl内部的UNIVERSAL包是其他所有包的祖先---以面向对象的视角来看那就是终极父类。UNIVERSAL提供了一些方法可供使用、继承和重写。

VERSION()方法

VERSION()方法会返回调用者(包或类)里的变量$VERSION的值。如果你提供了版本号作为参数且比调用者里$VERSION的值还要大,那就会产生一个异常。

假设模块HowlerMonkey的版本是1.23(也就是$VERSION的值是1.23),那么VERSION()的行为是这样的:

my $hm = HowlerMonkey->new;

say HowlerMonkey->VERSION; # prints 1.23
say $hm->VERSION; # prints 1.23
say $hm->VERSION( 0.0 ); # prints 1.23
say $hm->VERSION( 1.23 ); # prints 1.23
say $hm->VERSION( 2.0 ); # exception!

重写VERSION()方法要慎重,因为几乎不存在要重写的理由。

DOES()方法

DOES()方法是用来进行角色机制判断的,参数是调用者和角色名,如果调用者实现了该角色就返回真值(角色实现的机制可以有很多,如继承、委托、组成、角色应用或其他机制)。

默认DOES()的实现机制就是通过isa()方法,因为继承(isa()用于继承)就是这样一个机制:一个类实现了一个角色。假设给定一个类Cappuchin,那么它的DOES()行为可能是下面这样:

say Cappuchin->DOES( 'Monkey' ); # prints 1
say $cappy->DOES( 'Monkey' ); # prints 1
say Cappuchin->DOES( 'Invertebrate' ); # prints 0

某些情况下你可能会需要重写DOES()方法。

can()方法

can()方法用来判断调用者是否具有某方法。参数为方法名字符串,如果调用者具有该方法则返回该方法引用,否则就返回假值。你可以在类、对象、包上调用can()方法。

给定一个SpiderMonkey类,并且类中有screech方法:

if (my $meth = SpiderMonkey->can( 'screech' )) {...}
#将方法引用赋值给$meth

这样就能实现一种模式:调度方法前先检查该方法是否存在:

if (my $meth = $sm->can( 'screech' )
{
# method; not a function
$sm->$meth();
}

使用can()方法来测试一个包是否实现了一个指定的函数或方法:

use Class::Load;

die "Couldn't load $module!" unless load_class( $module );

if (my $register = $module->can( 'register' ))
{
# function; not a method
$register->();
}

Module::Pluggable

通过使用CPAN模块Class::Load能方便地进行模块加载。Module::Pluggable则能让你很容易地构建出插件管理系统。

isa()方法

isa()方法接受一个字符串,可以是类名或类型名(SCALAR, ARRAY, HASH, Regexp, IO,CODE)。可以把它当成类方法或实例方法来使用,如果调用者派生于或就是给定类(或调用者就是指定类型的bless过的引用)则返回真。

给定一个对象$pepper(一个哈希引用,类Monkey的神圣引用,继承自Mammal类),isa()方法的行为是这样的:

say $pepper->isa( 'Monkey' ); # prints 1
say $pepper->isa( 'Mammal' ); # prints 1
say $pepper->isa( 'HASH' ); # prints 1
say Monkey->isa( 'Mammal' ); # prints 1

say $pepper->isa( 'Dolphin' ); # prints 0
say $pepper->isa( 'ARRAY' ); # prints 0
say Monkey->isa( 'HASH' ); # prints 0

任何类都可以重写isa()方法。isa()方法有时候非常有用,比如如跟某些模块(Test::MockObject和Test::MockModule)协同工作时,或者代码没有使用角色时。要明白的是通常具有有充分的理由才会重写该方法。

类是否存在?
UNIVERSAL::isa()和UNIVERSAL::can()功能类似,你可以使用后者来安全地判断类是否存在,若UNIVERSAL::can($classname, 'can' )返回真,说明在某个地方定义了$classname类,但这个类存在却有可能不可用。

扩展UNIVERSAL

有个想法很有吸引力:将其他的方法也放到UNIVERSAL中,这样所有其他的类和对象中就都能使用这些方法了。但是,别这样做,特别是当代码不是你自己写的或者不是由你自己维护的时候,因为全局性的行为往往有着微妙的副作用。

偶尔借助UNIVERSAL来帮助调试修正代码还是可以的。例如Joshua benJore的UNIVERSAL::ref分发包就让几乎没用的ref()操作符变得有用。
UNIVERSAL::can和UNIVERSAL::isa分发包能帮助你调试多态相关的BUG。Perl::Critic也可以帮助你解决一些问题。

除非及其小心且有着实在而充分的理由,否则不应该将代码放到UNIVERSAL里面。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,670评论 0 9
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,056评论 25 707
  • 36.每日一典: 醍醐灌顶 [拼音] tí hú guàn dǐng [解释] 醍醐:酥酪上凝聚的油。用纯酥油浇到...
    清馨雨荷阅读 341评论 0 3
  • 2017/12/11遇到了两个自称从北京过来广州做市场调查的陌生人,心软对他们伸出了援手,我仅有的四百多块,被他们...
    愿你能被温柔以待阅读 282评论 0 0