perl中的UNIVERSAL 和AUTOLOAD

看到intermediate perl 14章,里面提到几个问题, 在网上的一些帖子(其他书)上看到一些和书上不对应的地方,于是自己测试了一下,inter perl上写的是正确的。

梳理一下如下:


Do all objects inherit from a common class

答:是的,perl中设定了一个类叫做 UNIVERSAL类, 在这个类中的定义的方法,被所有类继承,是最基本的类(不能乱用)。

what if a method is missing ?  如果一个方法不存在,会怎么样:

答:这个问题从两方面说:

一方面,   perl提供了测试的方法,即UNIVERSAL类中有三个方法isa(),can() 和VERSION(). 所有的类都能调用这三个方法(最好别重写)

      例1

        比如有一个对象 $tv_horse 是一个Horse对象, 可以用$tv_horse->isa('Horse') 测试,返回值为true,

            如果tv_horse是一个 racehorse的对象,是horse的派生类,也是正确的。

      例2

       $tv_horse->can('swim');   首先假定tv_horse是一个类对象或者类名, 这样就是判断该类中是否有swim方法。

另一方面,由于有继承存在,在测试method 是否missing的过程是一个搜索的过程,

                     先寻找自己再寻找基类,一路追查下去,RACEhorse 找horse ,horse 找animal,

                    最后找到 UNIVERSAL类。

                    如果都没有找到,can方法会返回false;

                   但是如果不是测试,而是直接调用, 例如:$tv_horse->swim(@arg),这种 方式,除了从下到上找一遍,perl还会寻找并尝试调用 这些类中的AUTOLOAD方法, 并将参数都传给该方法的@_变量中;并且 our  $AUTOLOAD 变量存储着 packagename::methodname ;这个例子就是  RACEHORSE::swim  。

                 即直接调用,有可能搜索两遍

可以用下面的代码修改看打印顺序。

#!/bin/perl
{ 
package Grandpa;
$name = "Gramps";
 sub greetme {
print "greetme in grandpa\n";
}
 sub AUTOLOAD {
 print "autoload in grandpa package.[autoload]\n";
}
}
 { package Parent;
our @ISA =qw(Grandpa);
sub greetme {
print "greetme in  parents\n";
}
 sub AUTOLOAD {
 print "autoload in parent package.[autoload]\n";
}
}
 {
 package UNIVERSAL;
 sub greetme{
	print "greeta in Universal\n";
 }
 sub AUTOLOAD {
 print "autoload in Universal package.[autoload]\n";
}
}
print Parent->can('greetme') ? "can\n":"cann't\n";
Parent->greetme();

总结: 测试的时候,要确定变量是 either a blessed reference or a class name as a scalar  ,直接调用的时候也是如此;不能确定就用eval{}

               测试和autoload无关,调用才可能找到autoload。

              把基本用不到的方法放在autoload里,再用eval q{ sub swim{  ...}}; goto &swim 配合使用,可以节约编译的时间。

             调用方法会先找UNIVERSAL 再找AUTOLOAD,书中练习题2也印证了这一点。

posted @ 2012-12-10 15:43  程序员杰诺斯  阅读(165)  评论(0编辑  收藏  举报