.NET을 사용하여 인사이드-아웃 Perl 클래스로 선언 된 3 개의 클래스가 Class::Std
있습니다. 이 3 개 중 하나에는 다음 $basket{ident $self}
과 같이 저장된 해시 참조가 있습니다 (Data :: Dumper의 출력).
$VAR1 = {
'auto' => {
'items' => {
'abc' => bless( do{\(my $o = undef)}, 'Item' )
},
'obj' => bless( do{\(my $o = undef)}, 'Category' )
}
};
이 해시 참조를 가져 와서 모든 것을 다시 만들어야합니다 (딥 클로닝). 내가 사용하려고 dclone
에서 Storable
이렇게 같은 :
my $new_basket = dclone $basket{ident $self};
해시를 인쇄 할 때 다른 메모리 주소를 얻습니다.
print $new_basket, "\n";
print $basket{ident $self}, "\n";
print $new_basket->{auto}->{items}, "\n";
print $basket{ident $self}{auto}->{items}, "\n";
print $new_basket->{auto}->{items}->{abc}, "\n";
print $basket{ident $self}{auto}->{items}->{abc}, "\n";
그러면 다음이 출력됩니다.
HASH(0x55d325306a20)
HASH(0x55d325245298)
HASH(0x55d323b35ca8)
HASH(0x55d3243dd968)
Item=SCALAR(0x55d323b45190)
Item=SCALAR(0x55d325306588)
내가 사용하지 않는 경우 dclone
와 사용하는 my $new_basket = $basket{ident $self}
대신에, 나는 같은 메모리 주소를 얻을. 를 사용 my $new_basket = { %{ $basket{ident $self} } }
하면 첫 번째 수준에서만 다른 주소를 얻습니다. 이는 얕은 복사본이어야합니다. 이 모든 것이 훌륭하고 예상되는 것 같습니다.
그래서 나에게는 dclone
주소가 다르기 때문에 실제로 모든 것을 딥 복사 한 것 같습니다 . 그러나 Item
다음과 같은 방법을 사용하려고 할 때 :
print $new_basket->{auto}->{items}->{abc}->get_added_on();
print $basket{ident $self}{auto}->{items}->{abc}->get_added_on();
나는 얻다:
Use of uninitialized value in print at lib/Basket.pm line 231.
2020-05-30
명확하게 dclone
내가 순진하게 생각했던 것보다 다르게 작동합니다.
이 전체 구조를 어떻게 딥 카피해야합니까? 여기에서 무슨 일이 일어나고 있는지 읽을 수있는 기사 / 문서에 대한 도움이나 참조에 감사드립니다.
한 가지 해결책은 생성자를 사용하여 전체 구조를 다시 만드는 것이지만 공간을 절약하고 dclone을 사용할 것이라고 생각했습니다. 그것은 분명히 그다지 잘 밝혀지지 않았습니다.
편집 : 최소 실행 가능한 데모를 제공하라는 요청을 받았습니다. 여기에 있습니다.
#!/usr/bin/env perl
use strict;
use warnings;
{
package A;
use Class::Std;
use Data::Dumper;
use Storable qw(dclone);
my %basket :ATTR;
sub BUILD {
my ($self, $ident, $args_ref) = @_;
$basket{$ident}->{auto} = {};
my $c = C->new({ date => q{2020-05-30} });
$basket{$ident}->{auto}->{items}->{abc} = $c;
return;
}
sub deep_clone {
my $self = shift;
print Dumper $basket{ident $self};
# the next line prints "2020-05-30" as expected
print $basket{ident $self}->{auto}->{items}->{abc}->get_added_on();
my $new_basket = dclone $basket{ident $self};
# "Use of uninitialized value in print at ./deep-clone.pl line 35."
print $new_basket->{auto}->{items}->{abc}->get_added_on();
}
}
{
package C;
use Class::Std;
my %added_on :ATTR( :get<added_on> );
sub BUILD {
my ($self, $ident, $args_ref) = @_;
$added_on{$ident} = $args_ref->{date};
return;
}
}
####
my $a = A->new();
$a->deep_clone();
새로 생성 된 "C"개체는에 추가되지 않았습니다 %added_on
.
클래스는이를 처리하기 위해 Storable에 대한 사용자 지정 처리기를 제공해야합니다.
"A"에 추가 :
sub STORABLE_freeze {
my ($self, $cloning) = @_;
my $ident = ident($self);
return "", {
basket => $basket{$ident},
# Other attributes...
};
}
sub STORABLE_thaw {
my ($self, $cloning, $serialized, $inner) = @_;
my $ident = ident($self);
$basket{$ident} = $inner->{basket};
# Other attributes...
}
"C"에 추가 :
sub STORABLE_freeze {
my ($self, $cloning) = @_;
my $ident = ident($self);
return "", {
added_on => $added_on{$ident},
# Other attributes...
};
}
sub STORABLE_thaw {
my ($self, $cloning, $serialized, $inner) = @_;
my $ident = ident($self);
$added_on{$ident} = $inner->{added_on};
# Other attributes...
}
그러면 문제없이 freeze
/ thaw
/ 사용할 수 있습니다 dclone
.
sub deep_clone {
my $self = shift;
#print Dumper $basket{ident $self};
CORE::say $basket{ ident $self }{auto}{items}{abc}->get_added_on();
my $clone = dclone($self);
#print Dumper $basket{ident $self};
CORE::say $basket{ ident $clone }{auto}{items}{abc}->get_added_on();
}
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다