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

Hi all, I have a perl module called theModule.pm which contains two public methods funcA and funcB. I also have a library module X.pm which contains another definition for funcB.
sub funcA { my ($self) = @_; require "X.pm"; $self->funcB(); }
perl unexpectedly call X's funcB rather than theModule's. Why would this be if i'm accessing it though theModules self pointer? how can i call theModule's funcB? thanks, michael

Replies are listed 'Best First'.
Re: perl calls unexpected function
by sauoq (Abbot) on Nov 05, 2002 at 20:58 UTC

    It's impossible to say for sure with the limited information you've given us but I'll hazard a guess. I suspect that your X.pm doesn't have a package statement. That would cause your funcB subroutine to be redefined when you require X from within your other module.

    One way to help yourself find these kinds of errors is to run with warnings enabled. I suggest you do so and, if perl spits out a warning like:

    Subroutine FuncB redefined at X.pm line 42.
    then my guess may well be right.

    -sauoq
    "My two cents aren't worth a dime.";
    
Re: perl calls unexpected function
by strider corinth (Friar) on Nov 05, 2002 at 20:21 UTC
    You don't say much about the relationship between the two. If you are only using theModule, X.pm ought never to be involved. Can you explain the relation between the two better?

    My only thought is that if by "library function" you mean that you're useing X.pm in theModule.pm, its funcB is overriding the one you're trying to call, as it should (if it's automatically exported).
    --

    Love justice; desire mercy.
Re: perl calls unexpected function
by Abigail-II (Bishop) on Nov 05, 2002 at 20:53 UTC
    You don't give us much information. Important are the packages of theModule.pm and X.pm. If the funcB's of both files are in the same package, the one in X.pm will replace the one in theModule.pm.

    But then, if you would warnings, Perl would tell you.

    Abigail

Re: perl calls unexpected function
by bart (Canon) on Nov 05, 2002 at 21:13 UTC
    So you have a theModule.pm and a X.pm. That are the modules, the files. But for method calls, it's the package, AKA the class, that $self is blessed in which matters, assuming it's an object. You don't mention the packages in the modules at all. Assuming $self is blessed in theModule.pm's package, say, "theModule", then of course the sub theModule::funcB that gets called as a method. If it were blessed in X.pm's class, say "X", then X::funcB would be called. That simple scheme ignores inheritance, i.e. how each package's @ISA array relates, but since each module, er, package, has a funcB method, I don't think it matters much. There must be some relationship, how else would the method funcA in theModule get called in the first place.

    You can override normal method lookup, like $self->X::funcB(). I think there recently was a thread on PerlMonks about it. It's an extension to the slightly more orthodox $self->SUPER::funcB() call mechanism.
    Update: found it: Invoking method in another package.

    Try this, all in one single script — which again shows that it's the package the method is in, that matters, not the source file. The BEGIN block for the assignment to @theModule::ISA is only to make sure it is set when the main code runs, as the module definition is underneath the main code in the script source.

    $obj = new theModule; $obj->funcA('own'); $obj->funcA('X'); $obj->funcA('SUPER'); package theModule; BEGIN { @ISA = 'Y'; } sub new { my %self; return bless \%self, shift; } sub funcA { my $self = shift; my $param = shift; print "\nfuncA in theModule got called, param = $param\n"; if($param eq 'own') { $self->funcB; } elsif($param eq 'X') { $self->X::funcB; } elsif($param eq 'SUPER') { $self->SUPER::funcB; } } sub funcB { my $self = shift; print "funcB in theModule is called\n"; } package X; sub funcB { my $self = shift; print "funcB in X is called\n"; } package Y; sub funcB { my $self = shift; print "funcB in Y is called\n"; }
    This prints:
    funcA in theModule got called, param = own funcB in theModule is called funcA in theModule got called, param = X funcB in X is called funcA in theModule got called, param = SUPER funcB in Y is called