如何间接访问 class 的属性

How to access the attributes of a class indirectly

这与我的另一个问题相似但不完全相同:

我正在编写一个测试来验证处理对对象的影响。但是我无法弄清楚如何获取一组已知对象属性的值,而是使用相同的代码进行测试。类似于以下内容(不起作用):

class A { has $.a, has $.b, has $.c };
my A $v .=new(:1a, :2b);

for <a b> { ok $v.{$_} > 0 }; # this does not work, but illustrates the intent.

如果我使用哈希而不是对象,那么很容易从知道键的哈希中获取值。

目前我能想到的就是测试每个属性:

ok $v.a > 0;
ok $v.b > 0;

此外,我不想查看对象的所有属性,这是 .^attributes 给我的,只是其中的一些。

您遇到的问题 – 像这样的测试使用 Hashes 比使用 Classes 更容易的原因 – 是您在需要时传入 Str传入一个对象。 Hashe 不会出现此问题,因为(默认情况下)Hash 键已经 字符串。

另一件需要记住的重要事情是,从技术上讲,没有任何方法可以从对象外部直接访问 Raku 对象的属性 – Raku 可以没有 public 属性,只有可以从 public 访问器方法访问的属性。这似乎是一个迂腐的区别,但在这里很重要:这意味着您需要一个可调用的 Method 对象(它比我在上一段中提到的“对象”更具体)。

正如 Tyil 在评论中提到的,您可以使用代码 for <a b> { ok $v."$_"() > 0 }; 将 Raku 带到 dwym。这样做的原因是最后的 () 强制 Raku 将 "$_" 的内插值视为 Callable,在这种情况下意味着 Method.

不过,我更愿意使用以下语法:

for $v.^methods.grep({.name ~~ 'a' | 'b'}) { ok $_($v) > 0}

(这利用了 $object.methodmethod($object) 在语法上等价的事实)。

请注意,我们有上面的 grep,因为您只想测试 A 的一些方法。然而,即使您想测试添加到 A 的所有方法,您可能仍然需要 grep 排除 BUILDALL,它由 $v.^methods(:local) 返回。我还没有弄清楚这是故意的还是错误(它不像 看起来 像本地方法)并且会感谢任何人对此的想法。