有没有一种简单的方法来测试 Moose 属性是否是只读的?

发布于 2024-08-27 13:51:10 字数 1386 浏览 16 评论 0原文

我目前使用块 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 只是一个true 或 false 值(即,但绝不是 coderef),通过使用 ! 对其进行否定。 双重否定也提供了这一点。因此,您可以在 is() 函数中使用 $is_read_only,而无需打印出 coderef。

请参阅下面 Robert P 的回答以获得最完整的答案。每个人都非常有帮助,并建立在彼此的答案和评论之上。总的来说,我认为他对我的帮助最大,因此他的答案现在被标记为已接受的答案。再次感谢 Ether、Robert P、frido 和 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.

I currently use a block eval to test that I've set an attribute as read-only. Is there a simpler way to do this?

Example from working code:

#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");




UPDATE


Thanks to friedo, Ether, and Robert P for their answers and to Ether, Robert P, and jrockway for their comments.

I like how Ether's answer ensures that $is_read_only is only a true or false value (i.e. but never a coderef) by negating it with a !. Double negation also provides that. Thus, you can use $is_read_only in an is() function, without it printing out the coderef.

See Robert P's answer below for the most complete answer. Everyone has been very helpful and built on each other's answers and comments. Overall, I think he's helped me the most, hence his is now marked the accepted answer. Again, thanks to Ether, Robert P, friedo, and jrockway.





In case you might be wondering, as I did at first, here is documentation about the difference between get_attribute and find_attribute_by_name (from 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦情居士 2024-09-03 13:51:10

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

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

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

因此,要在每种情况下测试属性已定义为 is =>; 'RO',需要检查写入和读取方法。您可以使用此子例程来完成此操作:

# 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());

Technically, an attribute does not need to have a read or a write method. Most of the time it will, but not always. An example (graciously stolen from jrockway's comment) is below:

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

This attribute will exist, but not have standard readers and writers.

So to test in every situation that an attribute has been defined as is => 'RO', you need to check both the write and the read method. You could do it with this subroutine:

# 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());
}

Alternatively, you could add a double negation before the last return to boolify the return value:

return !! (! $attribute->get_write_method() && $attribute->get_read_method());
等待我真够勒 2024-09-03 13:51:10

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(如果没有)。

As documented in 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() will get the writer method (either one you created or one that was generated), or undef if there isn't one.

∝单色的世界 2024-09-03 13:51:10

您应该能够从对象的元类中获取此信息:

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

请参阅 Class::MOP::Attribute 了解更多信息。

You should be able to get this from the object's metaclass:

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

See Class::MOP::Attribute for more.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文