diotalevi has asked for the wisdom of the Perl Monks concerning the following question:

I'm at a loss about any normal way to prevent Object::Deadly from having an ISA relationship with the UNIVERSAL class. I'm trying to protect myself against polluting things like UNIVERSAL::require (just search CPAN for other UNIVERSAL:: modules). Someone else has done sub UNIVERSAL::foo {...} and I want $my_obj->foo to fail to find UNIVERSAL::foo.

I've read all of CPAN's UNIVERSAL:: modules to get their current list of defined methods and have overrridden all of those. I've also used Devel::Symdump to search for any new, unknown methods at runtime. This is all patchwork because a new method could be defined right after I've finished doing my runtime checks for unknown methods.

Help?

$obj = bless {}, 'Bar'; $obj->violation; # succeeds with UNIVERSAL::violation package Bar; # no methods package UNIVERSAL; sub violation { ... }

Replies are listed 'Best First'.
Re: ->isn't('UNIVERSAL') - stopping UNIVERSAL pollution?
by chromatic (Archbishop) on Sep 05, 2006 at 22:16 UTC
    $ cd bleadperl $ rm universal.c

    In other words, I don't think you can prevent anyone from fiddling with your code. I can think of a few tricks, starting with:

    unshift @UNIVERSAL::ISA, 'ULTIMATE'; sub ULTIMATE::foo { ... }
Re: ->isn't('UNIVERSAL') - stopping UNIVERSAL pollution?
by hardburn (Abbot) on Sep 05, 2006 at 21:34 UTC

    The only solutions I can think of involve either hacking perl internals or source filtering. I'm sure you're aware of the problems with both of those.

    While the answer to "Can Perl do x?" is usally yes, the answer to "Can you stop Perl from doing x?" is usually no . . .

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

Re: ->isn't('UNIVERSAL') - stopping UNIVERSAL pollution?
by mreece (Friar) on Sep 05, 2006 at 21:39 UTC
    how about using something like Class::Can?
    my $obj = bless {}, 'Bar'; $obj->violation; package Bar; use Class::Can; CHECK { ## See what UNIVERSAL can do.. my %uni_can = Class::Can->interrogate('UNIVERSAL'); ## These are ok.. delete $uni_can{$_} foreach qw( can isa VERSION ); ## Anything left is not ok.. my @bad_methods = keys %uni_can; foreach my $method ( @bad_methods ) { *{ __PACKAGE__ . "::$method" } = sub { die "UNIVERSAL::$method not allowed"; }; } } package UNIVERSAL; sub violation { print "haha, a violation\n"; }
    it's not perfect. someone can put methods into UNIVERSAL that 'override' Bar's methods, so maybe you want to expand the 'ok' list to those methods declared by package Bar. there's probably another gotcha or two this doesn't account for, but it's a start..

      I'm already doing this with Devel::Symdump and watching for when B::sub_generation increments because then that's time to renew my prohibitions.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: ->isn't('UNIVERSAL')?
by merlyn (Sage) on Sep 05, 2006 at 20:27 UTC

      I'm pretty sure that doesn't work. First perl looks through all of ISA to see if the method can be found by name. If that fails it looks through all of ISA for AUTOLOAD by name. I can name an AUTOLOAD but that doesn't prevent something named in UNIVERSAL from being found.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: ->isn't('UNIVERSAL') - stopping UNIVERSAL pollution?
by ysth (Canon) on Sep 05, 2006 at 23:00 UTC

      Yeah... but I can't help wanting to at least ask if anyone has other ideas.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

        I have not delved much into Object::Deadly and the pod seems a bit unclear. It seems that the intent is to mock up an object to be used in testing code that should not call any methods of the object, containers and such.

        If you want no methods to be called why use an object?

        package Dont_touch; sub new { my $x; \$x; } 1;
        Since I don't know the underlying problem you're trying to solve, I'll shut my mouth now.

        Be well,
        rir