为什么可以修改 Raku 类上的只读数组属性?

Jul*_*lio 9 oop class rakudo raku

为什么在 Raku 类上可以修改只读数组属性,而另一方面,不能修改标量?

我怎样才能使@.baz“只读”?

class Boo {
    has $.bar;
    has @.baz;
};

my $boo = Boo.new;

$boo.baz = (1, 2); # works ... ?
say $boo.baz;

$boo.bar = 1; #fails ... expected
Run Code Online (Sandbox Code Playgroud)

我的乐道版本:

This is Rakudo version 2020.05.1 built on MoarVM version 2020.05
implementing Raku 6.d.
Run Code Online (Sandbox Code Playgroud)

Bra*_*ert 8

baz属性是只读的。

问题是该baz属性是Array具有可变元素的an 。


当你打电话时,$boo.baz你基本上得到了对数组的引用。

一旦获得了对数组的引用,您就可以执行通常可以对数组执行的任何操作。

say $boo.baz.VAR.name; # @!baz
Run Code Online (Sandbox Code Playgroud)

当您分配给一个数组时,您真正在做的是告诉该数组它将有新内容。

my @a = ('a','b','c');
say @a.WHICH; # Array|94070988080608

@a = (1, 2, 3);
say @a.WHICH; # Array|94070988080608
Run Code Online (Sandbox Code Playgroud)

请注意,.WHICH没有改变。那是因为它仍然是同一个数组。它只是有新的内容。

当您分配给公共数组属性时,会发生完全相同的事情。
您不是在分配新数组,而是在更改现有数组。

变量的所有行为都不是变量固有的,而是由对象处理的。
在数组的情况下,处理赋值的对象是Array


最简单的解决方法是重载自动生成的访问器方法。

class Boo {
    has $.bar;
    has @.baz;

    method baz () { @!baz.List }
}
Run Code Online (Sandbox Code Playgroud)

如果您从不打算更改 @!baz 中的值,您可以将其设为 List 本身

class Boo {
    has $.bar;
    has @.baz is List;
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为混淆并不是为什么你可以编辑元素——这可以通过对象内部可变来很容易地解释,但请考虑 `class A {has @.a is List}; 我的 $a = A.new(a=>(1,2)); $aa = (3,4)` 引用没有被更改,尽管看起来我正在尝试为其分配一个全新的列表。相反,完成了列表分配,显然试图保持原始所指对象的完整性 (3认同)