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

I've got a program that uses two different perl classes. Both classes are attempting to load the same common library via the use statement:
use myCommonLib;
The myCommonLib.pm does live in the INC path list. The main program includes both classes without issue, looking something like:
use class1; use class2;
I create objects of both classes and call their methods. When class2 attempts to call a function from myCommonLib, it gets an error saying that function doesn't exist. If I remove class1 from the program, then the method succeeds. Also if I reverse the include order, class2 then class1, I get errors on class1 function calls when it calls the common lib. Is there something I need to do to the myCommonLib.pm file to make it able to be included by two classes at once?

Replies are listed 'Best First'.
Re: use a package multiple times
by tj_thompson (Monk) on Dec 18, 2010 at 04:21 UTC

    I'm betting you're having a namespace issue. It would be handy to have a stripped down version of your code to look at, but here's my stab in the dark at what's going on.

    __START_OF_COMMON_LIB_FILE__ package Class1; sub new { return bless({}, 'Class1'); } sub method_1 { print "I'm method 1!\n"; } package Class2; sub new { return bless({}, 'Class2'); } sub method_2 { print "I'm method 2!\n"; } 1; __END_OF_COMMON_LIB_FILE__

    This will compile and run fun. You can create an object from class1 or class2. However, class1 will only be able to utilize the method1 sub and class2 will only be able to utilize the method_2 sub. The following code:

    use lib 'C:\tmp'; use CommonLib; my $class1_obj = Class1->new; my $class2_obj = Class2->new; $class1_obj->method_1; $class2_obj->method_2;

    Creates this output (note I've named my script tmp.pl):

    D:\tmp>tmp.pl I'm method 1! I'm method 2! D:\tmp>

    However, let's change the script so that Class1 tries to use method_2 and vice versa:

    use CommonLib; my $class1_obj = Class1->new; my $class2_obj = Class2->new; $class1_obj->method_2; $class2_obj->method_1;

    We get this output:

    D:\tmp>tmp.pl Can't locate object method "method_2" via package "Class1" at D:\tmp\t +mp.pl line 10. D:\tmp>

    This is because method_2 is only in the namespace for Class1. If you want a method that is defined in the file to be usable by both classes, you will have to define it for both classes.

    So in short, the only functions your classes will be able to access are the functions that are between their package declaration and the next package declaration. If you declare two packages in a row at the top of the file like:

    package Class1; package Class2; sub foo { }

    Then only the last declared package will have access to the functions you are defining. In the above case, you will be able to use Class2->foo, but Class1->foo will result in the same can't locate object error. As a matter of fact, Class1 will have no methods available since its namespace immediately ends.

      Alright lost in translation. Below a recreated version of the problem. Please pardon that class 1 & 2 look identical here, in code how they use the return value of myCommonLib::bar is where they differ. I'm providing 2 versions of myCommonLib.pm because I've tried it multiple ways, both produce the same error, that function class2::bar() doesn't exist.
      # This is tmp.pl use strict; use warnings; push(@INC, 'c:\perl\programs'); # this is where all code lives use class1; # Note, switching order here flips the error to class 1 use class2; my $C1 = new class1; my $C2 = new class2; $C1 -> FOO; $C2 -> FOO; # This line hits the error "undefined Class2::bar" # End tmp.pl file # start class1.pm file package class1; use strict; use warnings; use myCommonLib; #Contains function bar() sub new { ... } # builds an object, blesses it etc sub FOO { bar(); } 1; # End class1.pm # start class2.pm file package class2; use strict; use warnings; use myCommonLib; #Contains function bar() sub new { ... } # builds an object, blesses it etc sub FOO { bar(); # This line errors. myCommonLib::bar(); # Produces the similiar error that # "myCommonLib::bar()" doesn't exist } 1; # End class2.pm # File myCommonLib.pm Version 1 use strict; use warnings; sub bar { print "hello world"; } # End file myCommonLib.pm Version 1 # File myCommonLib.pm Version 2 package myCommonLib; use strict; use warnings; sub bar { print "hello world"; } 1; # End file myCommonLib.pm Version 2
        push(@INC, 'c:\perl\programs'); # this is where all code lives

        use happens at compile time, so if you want that to have an effect, you need to put it in a BEGIN block

Re: use a package multiple times
by samarzone (Pilgrim) on Dec 18, 2010 at 06:51 UTC

    Is the @INC (or use lib</c> statements) exactly same inside class1 and class2 when you use myCommonlib?. I have a feeling that both the classes are picking the module file from physically different locations and those two versions have differences.

    -- Regards - Samar