6

我目前使用一个块eval来测试我已将属性设置为只读。有没有更简单的方法来做到这一点?

工作代码示例:

#Test that sample_for is ready only
eval { $snp_obj->sample_for('t/sample_manifest2.txt');};
like($@, qr/read-only/xms, "'sample_for' is read-only");



更新

感谢friedo、Ether 和Robert P 的回答以及Ether、Robert P 和jrockway 的评论。

我喜欢 Ether 的答案如何$is_read_only通过用!. 双重否定也提供了这一点。因此,您可以$is_read_onlyis()函数中使用,而无需打印出 coderef。

有关最完整的答案,请参阅下面的 Robert P 的答案。每个人都非常乐于助人,并建立在彼此的答案和评论的基础上。总的来说,我认为他对我的帮助最大,因此他现在被标记为已接受的答案。再次感谢 Ether、Robert P、friedo 和 jrockway。



如果您可能想知道,就像我一开始所做的那样,这里是关于get_attributefind_attribute_by_name来自 Class::MOP::Class)之间区别的文档:

$metaclass->get_attribute($attribute_name)

    This will return a Class::MOP::Attribute for the specified $attribute_name. If the 
    class does not have the specified attribute, it returns undef.

    NOTE that get_attribute does not search superclasses, for that you need to use
    find_attribute_by_name.
4

3 回答 3

5

Class::MOP::Attribute中所述:

my $attr = $this->meta->find_attribute_by_name($attr_name);
my $is_read_only = ! $attr->get_write_method();

$attr->get_write_method()将获得 writer 方法(您创建的一个或生成的一个),如果没有,则为 undef。

于 2010-04-01T18:47:39.923 回答
5

从技术上讲,属性不需要具有读取或写入方法。 大多数时候会,但并非总是如此。下面是一个例子(从jrockway 的评论中偷来的):

has foo => ( 
    isa => 'ArrayRef', 
    traits => ['Array'], 
    handles => { add_foo => 'push', get_foo => 'pop' }
)

此属性将存在,​​但没有标准的读取器和写入器。

因此,要在每种情况下测试属性已定义为is => 'RO',您需要同时检查 write 和 read 方法。你可以用这个子程序来做到这一点:

# returns the read method if it exists, or undef otherwise.
sub attribute_is_read_only {
    my ($obj, $attribute_name) = @_;
    my $attribute = $obj->meta->get_attribute($attribute_name);

    return unless defined $attribute;
    return (! $attribute->get_write_method() && $attribute->get_read_method());
}

或者,您可以在最后一个之前添加双重否定return来布尔化返回值:

return !! (! $attribute->get_write_method() && $attribute->get_read_method());
于 2010-04-02T16:51:56.897 回答
3

您应该能够从对象的元类中获得它:

unless ( $snp_obj->meta->get_attribute( 'sample_for' )->get_write_method ) { 
    # no write method, so it's read-only
}

有关更多信息,请参见Class::MOP::Attribute

于 2010-04-01T18:48:19.537 回答