내부 Perl 클래스의 딥 클로닝-복사 된 객체에서 메서드를 사용하는 방법은 무엇입니까?

Pavelsaman

.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();
Ikegami

새로 생성 된 "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] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

부모 클래스 함수에서 상속 된 객체를 사용하는 방법은 무엇입니까?

분류에서Dev

앞에서 정의한 클래스 X 내부의 코드에서 나중에 정의 된 클래스 Y를 사용하는 방법은 무엇입니까?

분류에서Dev

블록 내부에서 객체를 가져 와서 다른 클래스 나 메서드에서 사용하는 방법은 무엇입니까?

분류에서Dev

클래스 내부의 개인 메서드를 사용하여 PyTorch 저장된 모델을 역 직렬화하는 방법은 무엇입니까?

분류에서Dev

C ++의 클래스 생성자 내부에서 스레드를 사용하는 방법은 무엇입니까?

분류에서Dev

Java-정의 된 클래스 내에서 메소드를로드하는 방법은 무엇입니까?

분류에서Dev

xcode에서 서로 두 클래스의 객체를 사용하는 방법은 무엇입니까?

분류에서Dev

Java 루트 클래스 즉, Object 클래스에 의해 마스킹 된 객체를 사용하여 원래 클래스 메서드를 호출하는 방법은 무엇입니까?

분류에서Dev

다른 클래스의 메서드에서 한 클래스의 객체를 사용하는 방법은 무엇입니까?

분류에서Dev

AutoMapper를 사용하여 클래스에 정의 된 순서로 객체를 매핑하는 방법은 무엇입니까?

분류에서Dev

PHP에서 특정 클래스에 정의 된 '클래스 상수'와 함께 defined () 메서드를 사용하는 방법은 무엇입니까?

분류에서Dev

Ruby의 상속 된 부모 메서드에서 자식 클래스를 얻는 방법은 무엇입니까?

분류에서Dev

메서드의 'this'로 다른 클래스를 사용하여 클래스 내부에 저장된 메서드를 호출하기위한 C ++의 올바른 구문은 무엇입니까?

분류에서Dev

유형을 사용하여 런타임에서 내부 클래스로 클래스를 정의하는 방법은 무엇입니까?

분류에서Dev

클래스 외부의 클래스 메서드 내에서 변수 또는 목록 또는 사전에 액세스하는 방법은 무엇입니까?

분류에서Dev

클래스 인수 및 메서드 인수에 대한 액세스 권한을 잃지 않고 클래스의 메서드 내부에서 이벤트 리스너 내에서 "this"키워드를 사용하는 방법은 무엇입니까?

분류에서Dev

Python3의 클래스 내부에서 자체 속성을 반복하는 방법은 무엇입니까?

분류에서Dev

파이썬의 클래스 내의 다른 함수에서 정의 된 (변수) 함수 내에서 변수를 사용하는 방법은 무엇입니까?

분류에서Dev

딥 러닝에서 기존 분류기에 새 클래스를 추가하는 방법은 무엇입니까?

분류에서Dev

Perl 6의 사용자 정의 클래스에 첨자를 추가하는 방법은 무엇입니까?

분류에서Dev

Kotlin의 내부 클래스에서 외부 클래스의 속성을 사용하는 방법은 무엇입니까?

분류에서Dev

Kotlin의 내부 클래스에서 조각 메서드를 호출하는 방법은 무엇입니까?

분류에서Dev

내 CSS의 새 클래스에 정의 된 클래스를 적용하는 방법은 무엇입니까?

분류에서Dev

Mirror를 사용하여 외부에서 정의 된 클래스에 액세스하는 방법은 무엇입니까?

분류에서Dev

TParallel. & For 루프에서 스레드로부터 안전한 객체의 데이터와 메서드를 사용하는 방법은 무엇입니까?

분류에서Dev

PHP : 현재 클래스에서 사용되는 트레이 트 메서드에서 부모 메서드를 호출하는 방법은 무엇입니까?

분류에서Dev

다른 클래스 Java의 객체로 매개 변수를 사용하여 메서드를 호출하는 방법은 무엇입니까?

분류에서Dev

Java에서 다른 클래스의 set 메소드를 사용하는 방법은 무엇입니까?

분류에서Dev

Python의 모든 클래스 메서드에 전역 변수를 사용하는 방법은 무엇입니까?

Related 관련 기사

  1. 1

    부모 클래스 함수에서 상속 된 객체를 사용하는 방법은 무엇입니까?

  2. 2

    앞에서 정의한 클래스 X 내부의 코드에서 나중에 정의 된 클래스 Y를 사용하는 방법은 무엇입니까?

  3. 3

    블록 내부에서 객체를 가져 와서 다른 클래스 나 메서드에서 사용하는 방법은 무엇입니까?

  4. 4

    클래스 내부의 개인 메서드를 사용하여 PyTorch 저장된 모델을 역 직렬화하는 방법은 무엇입니까?

  5. 5

    C ++의 클래스 생성자 내부에서 스레드를 사용하는 방법은 무엇입니까?

  6. 6

    Java-정의 된 클래스 내에서 메소드를로드하는 방법은 무엇입니까?

  7. 7

    xcode에서 서로 두 클래스의 객체를 사용하는 방법은 무엇입니까?

  8. 8

    Java 루트 클래스 즉, Object 클래스에 의해 마스킹 된 객체를 사용하여 원래 클래스 메서드를 호출하는 방법은 무엇입니까?

  9. 9

    다른 클래스의 메서드에서 한 클래스의 객체를 사용하는 방법은 무엇입니까?

  10. 10

    AutoMapper를 사용하여 클래스에 정의 된 순서로 객체를 매핑하는 방법은 무엇입니까?

  11. 11

    PHP에서 특정 클래스에 정의 된 '클래스 상수'와 함께 defined () 메서드를 사용하는 방법은 무엇입니까?

  12. 12

    Ruby의 상속 된 부모 메서드에서 자식 클래스를 얻는 방법은 무엇입니까?

  13. 13

    메서드의 'this'로 다른 클래스를 사용하여 클래스 내부에 저장된 메서드를 호출하기위한 C ++의 올바른 구문은 무엇입니까?

  14. 14

    유형을 사용하여 런타임에서 내부 클래스로 클래스를 정의하는 방법은 무엇입니까?

  15. 15

    클래스 외부의 클래스 메서드 내에서 변수 또는 목록 또는 사전에 액세스하는 방법은 무엇입니까?

  16. 16

    클래스 인수 및 메서드 인수에 대한 액세스 권한을 잃지 않고 클래스의 메서드 내부에서 이벤트 리스너 내에서 "this"키워드를 사용하는 방법은 무엇입니까?

  17. 17

    Python3의 클래스 내부에서 자체 속성을 반복하는 방법은 무엇입니까?

  18. 18

    파이썬의 클래스 내의 다른 함수에서 정의 된 (변수) 함수 내에서 변수를 사용하는 방법은 무엇입니까?

  19. 19

    딥 러닝에서 기존 분류기에 새 클래스를 추가하는 방법은 무엇입니까?

  20. 20

    Perl 6의 사용자 정의 클래스에 첨자를 추가하는 방법은 무엇입니까?

  21. 21

    Kotlin의 내부 클래스에서 외부 클래스의 속성을 사용하는 방법은 무엇입니까?

  22. 22

    Kotlin의 내부 클래스에서 조각 메서드를 호출하는 방법은 무엇입니까?

  23. 23

    내 CSS의 새 클래스에 정의 된 클래스를 적용하는 방법은 무엇입니까?

  24. 24

    Mirror를 사용하여 외부에서 정의 된 클래스에 액세스하는 방법은 무엇입니까?

  25. 25

    TParallel. & For 루프에서 스레드로부터 안전한 객체의 데이터와 메서드를 사용하는 방법은 무엇입니까?

  26. 26

    PHP : 현재 클래스에서 사용되는 트레이 트 메서드에서 부모 메서드를 호출하는 방법은 무엇입니까?

  27. 27

    다른 클래스 Java의 객체로 매개 변수를 사용하여 메서드를 호출하는 방법은 무엇입니까?

  28. 28

    Java에서 다른 클래스의 set 메소드를 사용하는 방법은 무엇입니까?

  29. 29

    Python의 모든 클래스 메서드에 전역 변수를 사용하는 방법은 무엇입니까?

뜨겁다태그

보관