Subject: | Broken SUPER semantics |
UNIVERSAL::can breaks SUPER semantics. See the attached test.
I have also attached a patch that solves this issue.
The patch to can.pm is based on the view that a subclass is allowed to
know everything about its superclass. This includes knowledge about
whether UNIVERSAL::can() can be used as a function. Also, I did see no
other way to support SUPER semantics.
I had to patch bad-input.t because my perl thinks that main->isa(''). I
don't know whether this is a feature...
Regards,
Peter du Marchie van Voorthuysen
Subject: | UNIVERSAL-can.patch |
diff -ru UNIVERSAL-can-1.12\lib\UNIVERSAL\can.pm UNIVERSAL-can\lib\UNIVERSAL\can.pm
--- UNIVERSAL-can-1.12\lib\UNIVERSAL\can.pm Sat Apr 01 07:15:10 2006
+++ UNIVERSAL-can\lib\UNIVERSAL\can.pm Fri Mar 09 15:38:45 2007
@@ -39,7 +39,7 @@
return _report_warning() unless defined $_[0];
# don't get into a loop here
- goto &$orig if $recursing;
+ goto &$orig if $recursing || caller->isa($_[0]);
# call an overridden can() if it exists
local $@;
diff -ru UNIVERSAL-can-1.12\t\bad-input.t UNIVERSAL-can\t\bad-input.t
--- UNIVERSAL-can-1.12\t\bad-input.t Sat Apr 01 07:15:10 2006
+++ UNIVERSAL-can\t\bad-input.t Fri Mar 09 15:31:57 2007
@@ -1,5 +1,7 @@
#!perl
+package test; # because main->isa('')
+
use strict;
use warnings;
Only in UNIVERSAL-can\t: SUPER-can.t
Subject: | SUPER-can.t |
use UNIVERSAL::can;
use strict;
use warnings;
package MyClass;
my @Caller;
sub can {
push @Caller, caller;
}
sub test {
my ($invocant, $method) = @_;
$invocant->SUPER::can($method);
}
package main;
use Test::More tests => 2;
my @Warning;
local $SIG{__WARN__} = sub { push @Warning, @_ };
MyClass->test("foo");
is_deeply(\@Warning, [], "CLASS->SUPER::can(METHOD) does not give a warning");
is_deeply(\@Caller, [], "CLASS->SUPER::can(METHOD) does not invoke CLASS->can(METHOD)");