Perl - 如何在子类中创建方法别名?

时间:2013-04-17 20:03:20

标签: perl class

我正在尝试为子类中的超类泛型方法创建别名,但它似乎不起作用。同一个类中的这个技巧可以工作,但它似乎不适用于超级/子级转换。这是一个真实的基本例子。前两个电话有效。第三次调用会生成有关未定义子例程的错误。我也试过使用SUPER :: cat,但这也不起作用。

package foo;

sub cat{
  print("inside foo\n");
}

*bird = \&cat;

package bar;

use base 'foo';

*dog = \&cat;

package main;

foo::cat();
foo::bird();
bar::dog();

4 个答案:

答案 0 :(得分:5)

您在面向对象的继承和简单的符号导入之间感到困惑。

正如你所说use base 'foo'宣布一个超类。这意味着,系统会检查foo是否有对bar中未显示的方法的任何调用。

但是*dog = \&cat不是方法调用:它只是一个全局赋值,因此搜索不会超出&bar::cat

如果您正在编写真正面向对象的代码,那么分配给*bar::dog就像那样会破坏继承机制。

要观察Perl的面向对象功能,请将glob分配移动到foo(它只是对方法进行别名)并使用方法调用语法进行调用。

在此代码中,bar没有自己的方法,并从foo继承所有,但代码按预期工作。

package foo;

sub cat {
  print("inside foo\n");
}

*bird = \&cat;
*dog = \&cat;


package bar;

use base 'foo';



package main;

bar->cat();
bar->bird();
bar->dog();

<强>输出

inside foo
inside foo
inside foo

答案 1 :(得分:3)

此:

*dog = \&cat;

应该是:

*dog = \&foo::cat;

答案 2 :(得分:2)

你应该写

sub dog { shift->cat(@_) }

(基本上是eta转换cat方法)而不是使用glob赋值,这样bar的子类可以覆盖或扩展cat而不会破坏barcatdog做同样事情的合同。

答案 3 :(得分:1)

考虑到Borodin更进一步的想法,假设你正在做正确的OO但是想要父类提供的方法的别名,并且只在这个子类中(和更深层次)。在这种情况下,您可能需要这样:

#!/usr/bin/env perl

package foo;

sub new { return bless {}, shift }

sub cat{
  print("inside foo\n");
}

*bird = \&cat;

package bar;

use base 'foo';

sub dog { $_[0]->can('cat')->(@_) }

package main;

my $bar = bar->new;
$bar->cat();
$bar->bird();
$bar->dog();

此机制在堆栈跟踪中保留dog。如果您不想这样,可以使用goto &sub表单,但由于您只应该知道原因,我不打算在此处举例。