0

我正在尝试为子类中的超类泛型方法创建别名,但它似乎不起作用。同一类中的这个技巧有效,但它似乎不适用于超级/子转换。这是一个真实的基本示例。前两个电话有效。第三次调用产生关于未定义子程序的错误。我也尝试过使用 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

4 回答 4

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
于 2013-04-17T21:03:42.200 回答
3

这个:

*dog = \&cat;

应该:

*dog = \&foo::cat;
于 2013-04-17T20:14:53.933 回答
2

你应该写

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

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

于 2013-04-17T21:14:18.540 回答
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表格,但是因为你应该只在你知道原因的情况下这样做,所以我不打算在这里举一个例子。

于 2013-04-17T21:15:22.730 回答