2010-06-22 43 views
2
my $t=TT::Pop->new(name => "shadowfax", color => "white"); 
my $w=TT::Pop::Subs->new($t); 

如何寫TT :: Pop :: Subs :: new(),這樣我就可以讓$ w減輕$ t中的所有屬性? 換句話說,我想用它的超類來初始化一個類。如何在Perl中將類的所有屬性複製到新的子類中?

在這種情況下,$ t中的所有屬性都應該是隻讀的,因此可以通過ref複製。 (我不知道的Perl能否使只讀的那些屬性)

回答

1

首先,不要打電話給你的方法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所暗示的那樣是不合格的。這個最大的問題是,你有這些限制:

  • 你的父類的對象必須是可克隆
  • 你的父母和孩子的類必須相同地實現存儲。
  • 訪問/ mutator方法不得使用屬性訪問類的名稱前綴。這意味着,Foo類專賣店在$self->{'Foo::attrib'} = 'value';attrib而富::酒吧把它們存儲在$self->{'Foo::Bar::attrib'} = 'value';

對於克隆,我會用Storabledclone。它具有作爲核心模塊的優勢,並且許多更具異國情調的對象實現爲Storable提供了掛鉤,以便克隆可以正常工作。

+1

如果我想讓這個類更具普遍性,那麼應該更好地顯式指定要複製的屬性。 而你的方式看起來更原子。 – Galaxy 2010-06-24 05:07:05

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

好了,這使得哈希的副本。

+0

您正在移動兩次。 – Ether 2010-06-22 14:51:13

+0

my $ w = TT :: Pop :: Subs-> new($ t); 因此,標量@_ == 2; – Galaxy 2010-06-22 15:34:54

1

使用克隆,使您的數據結構的深拷貝和祝福新的哈希:

use Clone qw(clone); 

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

或者,如果你想創建TT ::流行::替補拷貝構造函數:

# 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 當然,還有許多其他模塊可以做同樣的事情(數據結構的深層拷貝),只需選擇一個你最喜歡的模塊即可。

相關問題