如何间接访问 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 给我的,只是其中的一些。
您遇到的问题 – 像这样的测试使用 Hash
es 比使用 Class
es 更容易的原因 – 是您在需要时传入 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.method
和 method($object)
在语法上等价的事实)。
请注意,我们有上面的 grep
,因为您只想测试 A
的一些方法。然而,即使您想测试添加到 A
的所有方法,您可能仍然需要 grep 排除 BUILDALL
,它由 $v.^methods(:local)
返回。我还没有弄清楚这是故意的还是错误(它不像 看起来 像本地方法)并且会感谢任何人对此的想法。
这与我的另一个问题相似但不完全相同:
我正在编写一个测试来验证处理对对象的影响。但是我无法弄清楚如何获取一组已知对象属性的值,而是使用相同的代码进行测试。类似于以下内容(不起作用):
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 给我的,只是其中的一些。
您遇到的问题 – 像这样的测试使用 Hash
es 比使用 Class
es 更容易的原因 – 是您在需要时传入 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.method
和 method($object)
在语法上等价的事实)。
请注意,我们有上面的 grep
,因为您只想测试 A
的一些方法。然而,即使您想测试添加到 A
的所有方法,您可能仍然需要 grep 排除 BUILDALL
,它由 $v.^methods(:local)
返回。我还没有弄清楚这是故意的还是错误(它不像 看起来 像本地方法)并且会感谢任何人对此的想法。