我想将一个子标记分配给一个标量作为回调,同时归档继承行为,例如在下面的代码中调用foobar->warning()
或foobar->croaking()
将触发父级的功能,如果没有实施在foobar类中提供。根据附加要求,我可以将其分配给标量。
我能解决这个问题的唯一方法是反过来,即调用' warning_check_child'在' barqux'这将检查特定实现是否可用或执行自己的代码。
我希望那里有人有更好的解决方案,所以我可以在开始时避免现有的电话,或者至少确认没有更好的方法。
提前致谢
use strict;
use warnings;
warn "When methods accessed as class from foobar";
foobar->warning();
my $sub;
# assign class method to sub reference does not work
# $sub = \&foobar->warning;
# $sub->();
# Have the sub in other package check for custom functionality
$sub = \&barqux::warning_check_child;
$sub->();
### Child class
package foobar;
use parent -norequire, 'barqux';
sub warning{
warn "warning: foobar\n";
}
sub warning_check_child{
warn "warning: foobar";
}
### Parent class
package barqux;
sub warning{
warn "warning: barqux\n";
}
sub croaking{
warn "croaking: barqux\n";
}
sub warning_check_child{
if ( exists &foobar::warning_check_child ){
foobar::warning_check_child()
}
else {
warn "warning: barqux\n";
}
}
答案 0 :(得分:4)
听起来你需要UNIVERSAL::can
,如果类可以直接或通过继承执行该方法,它会向方法返回引用。
喜欢这个
use strict;
use warnings;
my $sub = FooBar->can('warning_check_child');
$sub->();
### Parent class
package BarQux;
sub warning{
warn "warning: BarQux\n";
}
sub croaking{
warn "croaking: BarQux\n";
}
sub warning_check_child{
warn "warning_check_child: BarQux\n";
}
### Child class
package FooBar;
use base 'BarQux';
sub croaking{
warn "croaking: FooBar\n";
}
<强>输出强>
warning_check_child: BarQux
答案 1 :(得分:1)
回调是代码引用,Perl对象是有福的引用,因此您可以保佑CODE引用以创建具有继承的回调。如果您将Foo::warning
转换为工厂,我认为您可以获得您之后的行为。
use 5.016; # needed for __SUB__
use strict;
use warnings;
package Bar {
sub warning {
my $class = shift;
my $self = sub {
__SUB__->warning_check_child();
say 'Bar::warning';
};
return bless $self, $class;
}
sub warning_check_child {
my $self = shift;
say 'Bar::warning_check_child';
}
}
package Foo {
use base 'Bar';
sub warning {
my $class = shift;
my $self = sub {
__SUB__->warning_check_child();
say 'Foo::warning'
};
return bless $self, $class;
}
}
package main {
my $f = Foo->warning();
$f->();
}
输出
Bar::warning_check_child
Foo::warning
如果Foo添加warning_check_child
方法,则会调用该方法。
注意:我在这里使用__SUB__
作为编写$self
的另一种方式,因为该对象是子例程。如果您仅限于5.16之前的Perl版本,则可以先预先声明$self
,然后在其上创建一个闭包:
sub warning {
my $class = shift;
my $self;
$self = sub {
$self->warning_check_child();
say 'Foo'
};
return bless $self, $class;
}