为什么可以修改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

我的rakudo版本:

This is Rakudo version 2020.05.1 built on MoarVM version 2020.05
implementing Raku 6.d.

解决方法

baz属性是只读的。

问题在于baz属性是具有可变元素的Array


调用$boo.baz时,基本上可以得到对该数组的引用。

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

say $boo.baz.VAR.name; # @!baz

分配给数组时,实际上是在告诉数组它将包含新内容。

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

@a = (1,2,3);
say @a.WHICH; # Array|94070988080608

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

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

变量的所有行为都不是变量固有的,而是由对象处理。
对于数组,处理分配的对象是Array


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

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

    method baz () { @!baz.List }
}

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

class Boo {
    has $.bar;
    has @.baz is List;
}
,

我的投票投给了@BradGilbert建议的'is List'版本...我尝试使用默认设置,并收到了以下令人敬畏的错误消息:

===SORRY!=== Error while compiling ...
Defaults on compound attribute types not yet implemented. Sorry.
Workaround: Create/Adapt TWEAK method in class Boo,e.g:

    method TWEAK() {
        @!baz := (initial values) unless @!baz;
    }

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...