这个问题困扰了我,但我已经解决了问题并将发布我的答案。
我有一个名为Parent
package Parent;
sub new {
my $c = shift;
my $s = {}, bless $s, $c;
return $s;
}
sub who {
return "parent";
}
1;
这个父类暴露了一个方法; who
。
我写了两个子课程:Child
和Freak
。只有Child
会覆盖who
。
package Child;
use base 'Parent';
sub who {
return "child";
}
1;
package Freak;
use base 'Parent';
1;
基类如何确定是否已覆盖基本who
方法?
我希望能够写出像这样的东西
package Parent;
sub new {
my $c = shift;
my $s = {}, bless $s, $c;
return $s;
}
sub who {
return "parent";
}
sub check {
my $self = shift;
my $is_overridden = 1; # what conditional should be here?
return $is_overridden ? "yes" : "no";
}
1;
我可以使用什么条件来确定子程序是否被覆盖?
答案 0 :(得分:7)
my $is_overridden = $self->can("who") != Parent->can("who");
请参阅UNIVERSAL
包的文档,其中定义了can
。
另外,我应该添加一个更哲学的注释 - 听起来你的压倒性是违反了Liskov Subsitution Principle,重构事物可能会更好,以至于重写一个方法并不是你必须要做的事情。调查代码中的其他地方。
答案 1 :(得分:4)
Parent->UNIVERSAL::can('who') ne Child->UNIVERSAL::can('who')
UNIVERSAL::can(PACKAGE,METHODNAME)
返回对给定方法名称在给定包中使用时将调用的子例程的引用。如果包不同但返回值相同,则意味着一个包从另一个包继承该方法(或者它们都是从公共源继承它)。此方法适用于多级继承:
package Parent;
sub foo { 42 }
sub bar { 19 }
sub baz { 47 }
package Child;
@Child::ISA = qw(Parent);
sub bar { 19 }
package Grandchild;
@Grandchild::ISA = qw(Child);
sub foo { 42 }
##############
package main;
print "foo:", Parent->UNIVERSAL::can('foo'),
Child->UNIVERSAL::can('foo'),
Grandchild->UNIVERSAL::can('foo'),"\n";
print "bar:", Parent->UNIVERSAL::can('bar'),
Child->UNIVERSAL::can('bar'),
Grandchild->UNIVERSAL::can('bar'),"\n";
print "baz:", Parent->UNIVERSAL::can('baz'),
Child->UNIVERSAL::can('baz'),
Grandchild->UNIVERSAL::can('baz'),"\n";
典型输出:
foo:CODE(0x17e26e8)CODE(0x17e26e8)CODE(0x17e2b38)
bar:CODE(0x17e27a8)CODE(0x17e29b8)CODE(0x17e29b8)
baz:CODE(0x17e2850)CODE(0x17e2850)CODE(0x17e2850)
答案 2 :(得分:0)
我对这种困境的回答如下:
包中方法的存在可以通过静态检查其CODE引用来确定,如下所示:
if( defined &Child::who ){
return "yes";
}
但是,由于父母可以被许多不同的孩子所覆盖,并且我不想手动引用所有这些孩子,我将获得对包裹的引用(这将是包裹以字符串形式命名并评估它。
sub check {
my $self = shift;
my $package = ref $self; # 'Freak' or 'Child', etc.
my $is_overridden = eval "defined &".$package."::who";
die "eval error occurred" if $@;
return $is_overridden ? "yes" : "no";
}
你有它!