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

When using autouse with an Object Oriented module, is it necessary to only predeclare the "new" function, or do you also have to autouse all methods (including "new") that you will be calling?

Replies are listed 'Best First'.
Re: use autouse with OOP
by btrott (Parson) on Jun 14, 2001 at 23:10 UTC
    The snippet that bikeNomad posted does work when your module name doesn't have a '::' in it, but I get errors when I try to use a module that isn't a top-level namespace:
    use autouse 'Net::SSH::Perl' => 'Net::SSH::Perl::new'; my $ssh = Net::SSH::Perl->new;
    When I run this I get:
    autouse into different package attempted at a.pl line 4 BEGIN failed--compilation aborted at a.pl line 4
    Looking into this a bit more, this is happening because autouse looks for the first occurrence of '::' in the function name, then compares everything before that to the module name you passed in. In my opinion it should be looking for the *last* occurrence of '::'. This is autouse with both 5.005_03 and 5.6.1.

    The following patch seems to fix the behavior:

    --- autouse.pm.old Thu Jun 14 12:08:05 2001 +++ autouse.pm Thu Jun 14 12:08:11 2001 @@ -39,7 +39,7 @@ my $closure_import_func = $func; # Full name my $closure_func = $func; # Name inside package - my $index = index($func, '::'); + my $index = rindex($func, '::'); if ($index == -1) { $closure_import_func = "${callpkg}::$func"; } else {
    But I haven't really explored all of the implications of this, as yet. :) Just be aware of this issue if you have the same problem.

    Personally, I don't use autouse for OOP (or really at all), because I tend to just require the module before I need to use it.

Re: use autouse with OOP
by bikeNomad (Priest) on Jun 14, 2001 at 22:36 UTC
    There is nothing special about new; it's just an often-used name for constructors. After all, this isn't C++ or Java.

    As far as autouse, all it does is to make stubs in the proper packages that will load the module if it isn't loaded. And you have to name the routines that you want to make stubs for. So assuming that the first subroutine that you call in your module is always "new", and that you aren't exporting anything from your module, it should be sufficient to do:

    use autouse 'MyModule' => 'MyModule::new';
    So that you'll get MyModule loaded when you go:
    my $mym = MyModule->new();
    Of course, if you call any other routines in your module first, they'd have to be added to the autouse list.

    Subsequent accesses to methods (subroutines) defined in MyModule will work fine after the first one causes the autoload.

      I tried use autouse 'My::Module' => 'My::Module::new'; and got: autouse into different package attempted at My/Module.pm (name of module changed).
      If I do: use autouse 'My::Module' => qw(new); I get: Bareword "My::Module" not allowed while "strict subs" in use at... when I call my $o = new My::Module;
      I realize I could call my $o = My::Module->new; But I would prefer not to change my code.

        A less-well-known feature of use and require is that it gives a "hint" to the compiler that My::Module might be a class name so that "new My::Module" gets parsed okay. You don't need this hint unless you also have a subroutine "new" in the current package.

        $ perl use strict; my $o= new My::Module; ^D Can't locate object method "new" via package "My::Module" $ perl use strict; sub new; my $o= new My::Module; ^D Bareword "My::Module" not allowed while "strict subs" in use $ perl use strict; BEGIN { $My::Module::VERSION= 1.0; } sub new; my $o= new My::Module; ^D Can't locate object method "new" via package "My::Module" $
        So I'd suggest you start moving away from the "new My::Module" syntax as you can see how fragile it is.

        As others have said, autouse.pm has an out-right bug in it.

        You problem implies that use autouse My::Module => qw(new); predeclares "sub new;" instead of (or in addition to) "sub My::Module::new". It took me a bit to spot the problem. autouse.pm is not meant for use with OO modules and the routines you list get exported. My::Module doesn't normally export new() for good reason!

        To get something like autouse.pm except for OO modules is actually much less work than what autouse.pm does. See (tye)Re: $PERL_USE=$PERL_USE: but use the better version in the reply.

        If you want something that only does AutoNew for a particular package:

        sub My::Module::new { require My::Module; undef &My::Module::new; goto &My::Module::new; }

                - tye (but my friends call me "Tye")
        Hmm... yes, you're right. There's a bug in autouse with modules whose names have '::' in them.

        I think you need to change the line in autouse.pm that says:

        my $index = index($func, '::');
        to:
        my $index = rindex($func, '::');
        You might want to submit this as a bug to the Perl Porters.

        update: wish I'd seen btrott's post before I figured the same thing out myself... would have saved some time. Anyway, I posted this to comp.lang.perl.moderated and comp.lang.perl.modules (wasn't sure which one it belonged in).