我已经意识到(困难的是(当其中一个操作数是字符串化过载的对象时,运算符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
中触发字符串化方法,然后比较得到的字符串。为什么它不起作用?究竟发生了什么?
我遇到这个问题的上下文是在一个同时使用autodie
和Try::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
重载。我们没有提供过载,也没有提供可以自动生成eq
的cmp
过载。因此,Perl将发出该错误。
启用fallback => 1
后,错误将被抑制,Perl将做它无论如何都会做的事情——将参数强制为字符串(这会调用字符串化重载或其他魔术(,并对它们进行比较。