当一个参数重载字符串化时,为什么"eq"不起作用



我已经意识到(困难的是(当其中一个操作数是字符串化过载的对象时,运算符eq会产生致命的运行时错误。

这里有一个最小的例子:

my $test = MyTest->new('test');
print 'yes' if $test eq 'test';
package MyTest;
use overload '""' => sub { my $self = shift; return $self->{'str'} };
sub new {
    my ( $class, $str ) = @_;
    return bless { str => $str }, $class;
}

运行此操作的结果是:

Operation "eq": no method found,
    left argument in overloaded package MyTest,
    right argument has no overloaded magic at ./test.pl line 7.

我对perlop的预期是,在两个操作数上都强制使用字符串上下文,在$test中触发字符串化方法,然后比较得到的字符串。为什么它不起作用?究竟发生了什么?

我遇到这个问题的上下文是在一个同时使用autodieTry::Tiny的脚本中。在try块中,I die带有一些要捕获的特定消息。但在catch块中,当我测试是否为$_ eq "my specific messagen"时,如果$_autodie::exception,则会给出运行时。

我知道我将不得不用!ref && $_ eq "..."替换$_ eq "...",但我想知道为什么。

您只重载了字符串化,而没有重载字符串比较。但是,如果指定fallback => 1参数,overload杂注将使用重载字符串进行字符串比较:

my $test = MyTest->new('test');
print 'yes' if $test eq 'test';
package MyTest;
use overload
    fallback => 1,
    '""' => sub { my $self = shift; return $self->{'str'} };
sub new {
    my ( $class, $str ) = @_;
    return bless { str => $str }, $class;
}

为什么这样做的详细信息:

当交给一个重载对象时,eq操作符将尝试调用eq重载。我们没有提供过载,也没有提供可以自动生成eqcmp过载。因此,Perl将发出该错误。

启用fallback => 1后,错误将被抑制,Perl将做它无论如何都会做的事情——将参数强制为字符串(这会调用字符串化重载或其他魔术(,并对它们进行比较。

最新更新