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

gvk*_*vkv 4 polymorphism perl constructor types

我有两个类:基类,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)
}
Run Code Online (Sandbox Code Playgroud)

问题是通过调用Foo::Base的构造函数,哈希现在将被祝福为Foo :: Base对象而不是Foo :: Base :: Sub对象.显而易见的解决方案只是将代码Foo::Base::new放入,Foo::Base::Sub::new但后来我重复代码.另一件事是Foo :: Base不是我的 - 所以我想避免在模块加载或不必要地分叉之后修改它.

在我看来,这个问题必须在此之前出现,因此必须有一个规范的解决方案.而且,它确实涉及类型强制,这通常不是Perl的问题.

那么有一个简单的修改,还是我错误的方式?

Com*_*ger 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;
}
Run Code Online (Sandbox Code Playgroud)

如评论中所述,Foo::Base构造函数必须使用以下两参数形式bless:

sub new {
    my $package = shift;

    my $self = bless {}, $package;

    # Other superconstructor stuff here

    return $self;
}
Run Code Online (Sandbox Code Playgroud)

当调用超类的构造函数时,$package将是子类.

  • 使用'parent'编译指示而不是直接操作@ISA. (4认同)
  • 请注意,这仅在超类构造函数使用`bless`的双参数形式时才有效,以便显式设置新对象的包名称.(这就是为什么你应该总是使用`祝福$ self,$ class`) (2认同)

Hyn*_*dil 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;
}
Run Code Online (Sandbox Code Playgroud)

注意,'Foo::Sub'没有实现new构造函数.

  • 我从教学的角度来看这个答案,但我不愿将建筑分成两部分.特别是当调用class-> new(...)是如此标准.感谢您的回答. (3认同)
  • 如果init()失败并且您希望整个构造因此失败,那么两阶段构造就不太可取了 - 您将最终得到一个部分构造的对象,其处于未知且可能无法使用的状态. (2认同)