什么是在Moose属性访问器上进行字符串重载的最佳方法?

10

我有一个类,想对它的id属性进行字符串重载。但是,Moose不允许在属性访问器上应用字符串重载。例如:

package Foo;
use Moose;
use overload '""' => \&id, fallback => 1;
has 'id' => (
    is => 'ro',
    isa => 'Int',
    default => 5,
);

package main;
my $foo = Foo->new;
print "$foo\n";

上述代码将会产生一个错误:

You are overwriting a locally defined method (id) with an accessor at C:/perl/site/lib/Moose/Meta/Attribute.pm line 927

我尝试了几种方法来解决这个问题:

  1. id 标记为 is => bare,并替换为自己的访问器: sub id {$_[0]->{id}}。但这只是一个hack。

  2. 使字符串重载器使用另一个方法,该方法只是将其委托回 id:sub to_string {$_[0]->id}

我想知道是否有更好的方法来处理这个问题?

2个回答

7
use overload '""' => sub {shift->id}, fallback => 1;

对我来说很好用。


这本质上是问题中第二个选项的简短语法。我不是说它不好,但仍然很有趣知道为什么问题中的第一种方法失败了。 - musiKk
更短的语法稍微更加简洁。考虑到三个参数的问题,我想这应该是前进的方式。 - stevenl

5
我相信你之所以出现错误,是因为\&id创建了一个占位符,以便稍后定义子例程,因为当定义引用时,Perl需要知道子例程的地址。 Moose有自己的检查来尝试避免覆盖您定义的方法,并向您报告此情况。
由于我认为您真正想做的是在对象用作字符串时调用 id 方法,就像这样:
use overload '""' => 'id', fallback => 1;

overload文档中得知:

字符串类型的值会被解释为方法名。


它不起作用。我仍然收到错误消息:Cannot assign a value to a read-only accessor at reader Foo::id (defined at - line 4) line 3 Foo::id('Foo=HASH(0x12ffa10)', undef, '') called at - line 12 - Hynek -Pichi- Vychodil
@Hynek,看起来overload正在将参数传递给方法,Moose将其解释为尝试设置属性。因此,您需要像在答案中所做的那样使用中间子程序。 - cjm
4
我看到这个错误是因为 overload 总是传递3个参数到 Overload - calling conventions 中的方法。 - stevenl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接