我有两个类:基类,Foo :: Base和派生类Foo::Base::Sub
。我想让Foo::Base::Sub
在构造函数的参数上做一些类型和数据检查 - 哈希 - 然后再祝福它。我试过覆盖Foo::Base->new
的构造函数,进行检查然后调用Foo::Base->new
(因为代码完全相同):
package Foo::Base::Sub;
sub new {
...check argument's type and data...
Foo::Base->new(%my_hash)
}
问题是通过调用Foo::Base
的构造函数,哈希现在将被祝福为Foo :: Base对象而不是Foo :: Base :: Sub对象。显而易见的解决方案就是将代码从Foo::Base::new
放入Foo::Base::Sub::new
,但之后我会重复代码。另一件事是Foo :: Base不是我的 - 所以我想避免在模块加载或不必要地分叉之后修改它。
在我看来,此问题必定已经出现,因此必须有一个规范的解决方案。而且,它确实涉及类型强制,这通常不是Perl的问题。
那么是否有一个简单的修改或我是否采取了错误的方式?
答案 0 :(得分:8)
标准的Perl习惯用法是使用SUPER
来调用继承链:
@Foo::Base::Sub::ISA = qw(Foo::Base);
sub new {
my $package = shift;
my $self = $package->SUPER::new();
# Other subconstructor stuff here
return $self;
}
如评论中所述,Foo::Base
的构造函数必须使用bless
的双参数形式:
sub new {
my $package = shift;
my $self = bless {}, $package;
# Other superconstructor stuff here
return $self;
}
当调用超类的构造函数时,$package
将成为子类。
答案 1 :(得分:7)
我习惯将其分为两部分,new
和init
。
package Foo::Base;
sub new {
my $class = shift;
my $self = bless {}, $class;
return $self->init(@_);
}
sub init {
my ($self, @params) = @_;
# do something initialization and checks
return $self;
}
package Foo::Sub;
use base 'Foo::Base';
sub init {
my ($self, @params) = @_;
# do something initialization and checks
$self = $self->SUPER::init(@params);
# do something other if you wish
return $self;
}
请注意,'Foo::Sub'
未实现new
构造函数。
答案 2 :(得分:0)
您可能希望了解调用super的各种方法。 SUPER模块可能有效但我自己没有尝试过。
答案 3 :(得分:-1)
虽然'超级'答案确实描述了你想要的东西,但你可以(在更一般的情况下)通过这样的方式调用任意包中的方法代码:
$object = Foo::Class->new(...);
$object->Bar::Class::method(@args);
Bar :: Class ::方法将正常进行,如:
package Bar::Class;
sub method {
my ($self, @args) = @_;
只有$ self会与平时不同。当然,这样做而不是SUPER可能是你做错事的一个标志。
比较NEXT和Perl 5.10的'mro'。