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是否可以只读取这些属性)
答案 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建议的那样重新出现。最大的问题是你有这些限制:
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;
}
好吧,这会产生哈希的副本。