如何将类的所有属性复制到Perl中的新子类?

时间:2010-06-22 14:04:37

标签: perl class

my $t=TT::Pop->new(name => "shadowfax", color => "white");
my $w=TT::Pop::Subs->new($t);

如何编写TT :: Pop :: Subs :: new()以便我可以让$ w cantains来自$ t的所有属性? 换句话说,我想用超类初始化一个类。

在这种情况下,$ t的所有属性都应该只读,因此可以接受ref复制。 (我不确定perl是否可以只读取这些属性)

3 个答案:

答案 0 :(得分:2)

使用Clone制作数据结构的深层副本并祝福新哈希:

use Clone qw(clone);

my $w = bless clone($t), 'TT::Pop::Subs';

或者如果你想在TT :: Pop :: Subs中创建一个拷贝构造函数:

# In TT::Pop
use base 'Clone'; 

# In TT::Pop::Subs
sub new {
  my ($class, $source) = @_;
  return bless $source->clone, $class;
}

在此处详细了解克隆:http://search.cpan.org/~rdf/Clone-0.31/Clone.pm 当然还有很多其他模块可以做同样的事情(数据结构的深层复制),只需选择你最喜欢的模块。

答案 1 :(得分:2)

首先,不要将您的方法new称为promote或类似的方式。

我对如何处理这种设计感到好奇。我最初的反应是你应该使用访问器方法并“手动”将值复制到一个新对象中。

sub promote {
    my $class = shift;
    my $obj   = shift;

    my %args = map { $_ => $obj->$_ } qw(
        attribute
        another
        this_one
        that_one
    );

    return $class->new( %args );
}

这使您的子类与父级中的更改隔离开来。

您的父类现在可能成为内部对象或其他不具有clone的内容。父级中的关键属性可以由从其他属性生成它的方法替换。

显然,父母和子女之间的一定程度的耦合是不可避免的。但这种方法有助于减少它。

另一种看似显而易见的方法是使用clone并像jkramer建议的那样重新出现。最大的问题是你有这些限制:

  • 您的父类对象必须是可克隆的
  • 您的父类和子类必须以相同的方式实现存储。
  • accessor / mutator方法不得使用类名前缀进行属性访问。这意味着Foo类将attrib存储在$self->{'Foo::attrib'} = 'value';中,而Foo :: Bar将它们存储在$self->{'Foo::Bar::attrib'} = 'value';

对于克隆,我会使用Storable的{​​{1}}。它具有作为核心模块的优势,并且许多更奇特的对象实现为Storable提供了钩子,以便克隆能够正常工作。

答案 2 :(得分:1)

sub new {
    my $this = shift;
    my $class = ref($this) || $this;
    my $SuperClass = shift;
    my $self = ref($SuperClass)?{%$SuperClass,}:{};
    bless $self, $class;
    return $self;
}

好吧,这会产生哈希的副本。