我无法弄清楚多态如何在Perl中起作用的解释。我理解多态性意味着什么,但我想弄清楚它在perl中的内部工作原理。有人能指出一些解释它的文档。我所做的所有谷歌搜索都给出了perl中多态性的例子,但不是perl如何使其工作。
答案 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中调用函数。因此,强类型语言必须创建允许多态的特殊机制。