我正在尝试为子类中的超类泛型方法创建别名,但它似乎不起作用。同一个类中的这个技巧可以工作,但它似乎不适用于超级/子级转换。这是一个真实的基本例子。前两个电话有效。第三次调用会生成有关未定义子例程的错误。我也试过使用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();
答案 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
而不会破坏bar
的cat
和dog
做同样事情的合同。
答案 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
表单,但由于您只应该知道原因,我不打算在此处举例。