如何在我的父类中创建一个对象,但是将它保存到Perl中的子类中?

时间:2009-12-29 14:18:05

标签: perl constructor types polymorphism

我有两个类:基类,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的问题。

那么是否有一个简单的修改或我是否采取了错误的方式?

4 个答案:

答案 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)

我习惯将其分为两部分,newinit

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'。