in reply to Sharing and over-riding package functions

You should note that the use vars qw(@variable) is an outdated way of creating package globals - the syntax our @variable (parallel to my) is preferable, though both are functional.

I'm not quite following your logic on how you are building your modules. Generally you only override a method in an inheritance context (perltoot) - it looks more like you should be doing selective importing into whichever program you are writing.

use ModuleA qw(func1 func2); use ModuleB qw(func3);

particularly since you are already using exporter. You could certainly use this approach to build suite sets if you just wanted one use statement at the head of your script.

Replies are listed 'Best First'.
Re^2: Sharing and over-riding package functions
by ruzam (Curate) on Dec 11, 2008 at 18:11 UTC

    Selective importing is what I'm trying to do inside of replace::functions.

    When program B calls 'use replace::functions qw(func1)', I don't want program B to a have to know or care if func1 is coming from replace::functions or orig::functions.

      Right, so you think of your packages as function suites.

      package Functions::Base; use strict; use Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw(func1 func2 func3); sub func1 { print "hello"; } sub func2 { print "kind"; } sub func3 { print "world"; } return 1;

      and

      package Functions::Alternate; use strict; use Exporter; use Functions::Base (@Functions::Base::EXPORT_OK); our @ISA = qw(Exporter); our @EXPORT_OK = (@Functions::Base::EXPORT_OK, qw (funcx funcy) ); # func1 is going to be replaced with our own no warnings 'redefine'; sub func1 { print "goodbye"; } # func2 is going to be replaced with our own sub func2 { Functions::Base::func2(); print "(haha)"; } use warnings 'redefine'; # func3 is reused from orig::functions unchanged # a couple new functions sub funcx { print "new x"; } sub funcy { print "new y"; } return 1;

      and

      package Functions; use strict; use Exporter; use Functions::Base qw(func1 func3); use Functions::Alternate qw(func2); our @ISA = qw(Exporter); our @EXPORT_OK = (func1 func2 func3); return 1;

      so for subroutines

      use strict; use Functions::Base qw(func1 func2 func3); func1; func2; func3; print "\n";

      or

      use strict; use Functions::Alternate qw(func1 func2 func3); func1; func2; func3; print "\n";

      or

      use strict; use Functions qw(func1 func2 func3); func1; func2; func3; print "\n";

      I'd also note that by printing the functions which contain print statements, you are uselessly printing the functional return values, which will be 1. Thus, you are appending 1 to the end of your outputs for each call.

        That's basically the same code I started with. The only real difference between your example and mine is that in Functions::Alternate I chose not imported the functions I was replacing to avoid redefine warnings, where as you chose to import all functions and quiet the redefine warnings. I must admit though, your slant avoids having to manually keep track of what functions have been replaced, which is a nice touch.

        But if you read down to my reply to rir you'll find that this approach fails when functions call functions within the same package

        Consider this:
        sub func1 { print "goodbye"; func2(); }

        If func1 isn't also replaced, it will execute Functions::Base::func2() when it's called, not the Functions::Alternate::func2() we're trying to replace. I never realized this when I started the post.