首页 > 解决方案 > 是否可以在不定义 getter 的情况下访问 Perl 包的 ATTR?

问题描述

我目前正在从事 Perl 5.8 项目。我的包裹看起来像:

package Foo::Bar;

use strict;
use warnings;
use Class::Std;

our @EXPORT_SAFE = qw(Class::Std);

my %baz :ATTR;

sub BUILD {
  my ($self, $ident, $args) = @_;
  
  $baz{$ident} = $$args{something};
}

我没有公开baz任何吸气剂,但我想获取它的内容以进行单元测试。有什么办法可以在 Perl 中做到这一点?

例如在 Ruby 中你可以some_instance.instance_variable_get("@#{name}")

非常感谢您提前

标签: perl

解决方案


TL;博士

一般情况下的答案是“这取决于(但可能)”。

你的答案是“不”。

细节

在 Perl 中实现类和对象没有固定的方法。在大多数情况下,对象将是对哈希的祝福引用。在这些情况下,您可以简单地将对象引用视为哈希引用并直接查找键。所以,像这样的代码:

my $baz = $obj->{baz};

但是,您没有使用最常用的方法来构建 Perl 对象,而是使用Class::Std。而 Class::Std 做的事情却完全不同。Class::Std 使用一种称为“由内而外对象”的方法,该方法由 Damian Conway 在Object Oriented Perl中推广,并且在大约 20 年前非常流行。

在普通对象中,每个对象都有一个哈希值。键是属性名称,值是属性值。对于由内而外的对象,每个属性都有自己的哈希值。键是对单个对象的字符串化引用,值是该对象的属性值。

实际上,“标准”方法是:

$object{attr} = value;

由内而外的方法是:

$attr{object} = value;

人们喜欢由内而外的对象的一大原因是属性散列可以是存储在类源代码中的词法变量。这意味着它们是真正私有的,不能从类外部访问——除非使用提供的访问器方法。如果你想强制 Perl 实现一种更强大的封装,这很好。但是如果你想以你在这里所做的方式突破这种封装,那就太糟糕了。

所以不行。在你的情况下,你不能这样做。


推荐阅读