On Mon, Nov 03, 2003 at 12:37:49PM -0800, Michael Jacob wrote: > Hi all, > > As we have seen in the last month, both UNIVERSAL:: and UNIVERSAL.pm are > broken in concept. Multiple fixes/workarounds have been discussed, but > none took. So I took some time to layout the root of the problem in my > head. This is the result: > > > 1.) Change can()'s semantics. > > can() returns unexpected reults if any module changed something in the > UNIVERSAL:: package. This can make other modules fail, we have seen this > with DBI(!)... So: > > Starting with Perl 5.8.12, can() shall not search the package UNIVERSAL > for inherited methods unless UNIVERSAL is explicitly included in the > @ISA of the class tested against. > > This means that > > @Foo::Bar::ISA = qw(); > (bless {}, 'Foo::Bar')->can('can') > > will return false, but > > @Foo::Bar::ISA = qw( UNIVERSAL ); > (bless {}, 'Foo::Bar')->can('can') > > will return true. > > Starting with Perl 5.8.10, can() will issue a warning when returning a > value that it would not return with above change implemented: "Testing > for methods implicitly inherited from UNIVERSAL with can() is > deprecated" > > I think, this change should not break any well written module. Testing > for any method that's in UNIVERSAL is just useless, we already know > before the test that it must be there. Any module that want's to know if > there is some additional method in UNIVERSAL:: can just test against > UNIVERSAL->can() directly. But C<can> doesn't just test for existance, it returns a code ref of the method if found. Thus C<$code = $obj->can('can')> is perfectly reasonable, and should return a ref to UNIVERSAL::can if there aren't any others in the inheritance chain. -- You live and learn (although usually you just live).Thread Previous | Thread Next