You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Perl 6深克隆对象仍关联?为何自动访问器能修复克隆问题

问题解析:Perl 6克隆对象时数组关联的原因及解决方法

为什么私有数组属性时克隆对象与原对象共享数组?

  • 你写的multi method clone并未覆盖Perl 6默认的clone方法(来自Mu类的非multi方法),调用clone时实际执行的是Mu的浅复制逻辑:直接复制属性的引用,而非深复制数组本身。
  • 私有数组@!counters是引用类型,克隆对象和原对象会共享同一个数组实例,修改任意一个都会影响另一个,导致最后一项测试失败。
  • 你试图用nextwith传递:counters(@!counters.clone)的逻辑完全无效,因为nextwith用于多候选方法的调度,而Mu的clone不是multi方法,你的multi版本根本不会被调用。

为什么改成公共自动访问器后测试通过?

当你把@!counters改成@.counters时,Perl 6自动生成了公共数组访问器,同时改变了属性的内部存储:

  • 自动访问器对应的属性是容器化数组,Mu的默认clone在复制这个容器时,会自动对数组执行浅克隆(创建新数组实例,复制原数组元素)。
  • 此时克隆对象的数组是原数组的副本,而非同一个引用,修改克隆对象的数组不会影响原对象,测试自然通过。

正确的克隆实现方案

要彻底解决问题,需正确覆盖默认clone方法,手动实现深复制,同时避免TWEAK清空数组:

use v6.d;
use Test;

class Numeration {
    has Int @!counters is default(1);
    
    # 修改TWEAK,仅在首次创建对象时清空数组,克隆时跳过
    submethod TWEAK(:$!is-clone = False) {
        @!counters = Nil unless $!is-clone;
    }

    # 覆盖默认clone方法(非multi版本)
    method clone {
        my $clone = self.new(:is-clone, :counters(@!counters.clone));
        $clone
    }

    # 原有方法保持不变
    multi method Str () {
        @!counters>>.Str.join('.') ~ '.'
    }
    multi method Str ( $n ) {
        @!counters[^$n]>>.Str.join('.') ~ '.'
    }
    multi method inc (Int() $level) {
        @!counters[$level - 1]++;
        @!counters.splice($level);
        self
    }
    multi method inc () {
        self.inc(1)
    }
    method reset () {
        @!counters = Nil;
        self
    }
    method set (Int() $level, $value ) {
        @!counters[$level - 1] = $value;
        self
    }
}

# 测试代码
my Numeration $n .= new;
$n.inc;
is $n.set(5,3).Str, '2.1.1.1.3.', 'set beyond last extent puts 1 in intermediate position';

my $m = $n.clone;
is $m.Str, '2.1.1.1.3.', 'same as n';
is $m.inc(3).Str(5), '2.1.2.1.1.', 'increments properly';
is $n.Str(5), '2.1.1.1.3.', 'incrementing m leaves n unchanged';

done-testing;

关键修正说明

  • 将multi method clone改为method clone,确保覆盖Mu的默认clone方法。
  • 给TWEAK添加:$!is-clone参数,避免克隆时清空数组。
  • 手动调用self.new创建新对象,传入克隆后的数组,确保实现深复制。

内容的提问来源于stack exchange,提问作者Richard Hainsworth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 08:44:55