我已经意识到(艰难的方法)当一个操作数是一个带有重载字符串化的对象时,运算符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
块中,我die
包含一些特定的消息。但是在catch
块中,当我测试是否$_ eq "my specific message\n"
时,如果$_
是autodie::exception
,则会给出运行时。
我知道我必须用$_ eq "..."
替换!ref && $_ eq "..."
,但我想知道原因。
答案 0 :(得分:21)
您只重载了字符串化,而不是字符串比较。但是,如果您指定overload
参数,则fallback => 1
pragma将使用重载的字符串进行字符串比较:
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
重载。我们没有提供重载,并且我们没有提供cmp
重载,eq
可以自动生成。因此,Perl会发出该错误。
使用fallback => 1
enabled,错误被抑制,Perl将执行它无论如何会做的事情 - 强制字符串的参数(调用字符串化重载或其他魔法),并比较它们。