Perl多态性如何工作?

时间:2012-06-13 17:14:42

标签: perl

我无法弄清楚多态如何在Perl中起作用的解释。我理解多态性意味着什么,但我想弄清楚它在perl中的内部工作原理。有人能指出一些解释它的文档。我所做的所有谷歌搜索都给出了perl中多态性的例子,但不是perl如何使其工作。

5 个答案:

答案 0 :(得分:15)

当对象或类上有method is invoked时,Perl会查看该方法是否由类本身直接提供。

因为classes are simply Perl packages,只需要查找子程序&Class::method的存在。

如果没有找到这样的子例程,Perl会检查同一个包中的@ISA数组(即@Class::ISA),其中包含该类的基类列表,并对每个包执行相同的检查/ class出现在那里。

这些类中的每一个反过来也可能有一个@ISA数组,因此搜索是递归的。

最后,如果通过此方法找不到该方法,Perl会在特殊包UNIVERSAL中查找子例程&UNIVERSAL::method

此时失败继续调用AUTOLOAD系统,但这实际上超出了多态性的原则。

无法在任何地方找到合适的匹配方法会引发异常。

答案 1 :(得分:9)

来自Object Oriented Perl的第7章,Damian Conway,Manning(2000)被称为多态性。十页。

但是,请注意,如果你来自C ++或Java或C#或类似的东西,那么在Perl中对“多态”的了解并不多。我甚至会说多态性的概念使事情变得比在Perl中更复杂。

我认为Perl程序员应该努力理解的机制是方法查找的工作原理。答案是:深度优先递归扫描@ISA数组包。

一个例子,让我们做$o->bla。我们的$o被祝福A包,其中没有bla的实现。但它继承自第一个B,然后是C@ISA = ('B', 'C'))。所以我们先在B进行查找。它也没有定义方法。如果它有父类,我们将继续在那里查找。但事实并非如此。所以我们现在研究C,幸运的是它确实有方法,否则会出现运行时错误,因为最后的程序包UNIVERSAL也没有定义bla

答案 2 :(得分:5)

对象方法调用基本上是以下的优化*版本:

my $class = ref($_[0]);
my @isa = mro::get_linear_isa($class);
for my $pkg (@isa) {
   if (exists(&{$pkg.'::'.$method_name})) {
       return &{$pkg.'::'.$method_name};
   }
}

ref获取与该对象关联的类的名称。该类存储在对象的变量中。

$ perl -MDevel::Peek -e'my $o = {}; Dump($o); bless($o, "SomeClass"); Dump($o);'
SV = IV(0x9e4ae0c) at 0x9e4ae10
  REFCNT = 1
  FLAGS = (PADMY,ROK)
  RV = 0x9e317d0
  SV = PVHV(0x9e36808) at 0x9e317d0
    REFCNT = 1
    FLAGS = (SHAREKEYS)
    ARRAY = 0x0
    KEYS = 0
    FILL = 0
    MAX = 7
    RITER = -1
    EITER = 0x0
SV = IV(0x9e4ae0c) at 0x9e4ae10
  REFCNT = 1
  FLAGS = (PADMY,ROK)
  RV = 0x9e317d0
  SV = PVHV(0x9e36808) at 0x9e317d0
    REFCNT = 1
    FLAGS = (OBJECT,SHAREKEYS)        <----
    STASH = 0x9e323d0   "SomeClass"   <----
    ARRAY = 0x0
    KEYS = 0
    FILL = 0
    MAX = 7
    RITER = -1
    EITER = 0x0

get_linear_isa基于@ISA包中的$class以及其中指定的包的@ISA

由于类名在对象中,并且由于Perl可以在运行时检查其符号表,因此不需要虚拟方法表来提供多态性。

* - 它缓存哪个包为类$ class提供方法$ method_name。此外,它肯定不会预先计算整个线性ISA,而是根据需要计算。

答案 3 :(得分:1)

这很适合基于继承的多态性,并且可以了解Perl具体做什么。我一直使用12.5章。 Programming Perl中的类继承作为这些事物的参考。

答案 4 :(得分:1)

多态性只是不同类型的对象响应同名方法调用的想法。弱类型语言(如Perl)是“隐式多态”。

例如,CGI对象,Apache2::Request对象和Plack::Request对象都具有param方法,该方法将返回HTTP请求的参数。我可以编写一个接受对象作为参数的函数,并在该对象上调用param方法,并获取HTTP请求参数,而不知道它是什么类型的对象。

强类型语言不能以这种方式工作,因为它们的函数指定了参数的数据类型。如果期望Dog之一,我无法使用Cat类型的对象在Java中调用函数。因此,强类型语言必须创建允许多态的特殊机制。