Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one create a child module?

Tags:

perl

I've been out of the Perl world for way too long. I want to create a child module and access its functions. I'm basically just missing how to connect these and access the methods.

Parent example: WWW::Foo

package WWW::Foo
use strict;
use warnings;
require Exporter;
our @ISA = qw(Exporter);
our %EXPORT_TAGS = ( 'all' => [ qw( new ) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw( );
our $VERSION = '0.01';

sub new {
    my ($package) = @_;

    $package::account_name = "Paul";
    return bless({}, $package);
}

Child example: WWW::Foo::Bar

package WWW::Foo::Bar
use strict;
use warnings;
require Exporter;
our @ISA = qw(Exporter);
our %EXPORT_TAGS = ( 'all' => [ qw( new ) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw( );
our $VERSION = '0.01';

sub print_name {
    my ($package) = @_;
    # Access parent's package and do basic print.
    return;
}

Example Script

#!/usr/bin/perl -w
use strict;
use WWW::Foo;
use WWW::Foo::Bar;

my $foo = new WWW::Foo();
# Access WWW::Foo::Bar's print_name function
like image 615
Paul J Avatar asked Jul 30 '26 23:07

Paul J


2 Answers

Here is a short working example.

use strict;
package WWW::Foo;

sub new {
    my ($package) = @_;
    my $self = bless {}, $package;
    $self->{account_name} = "Paul";
    return $self;
}


package WWW::Foo::Bar;
use base "WWW::Foo";

sub print_name {
    my ($self) = @_;
    my $name = $self->{account_name};
    print "Hello $name\n";
}


package main;
my $foo = WWW::Foo::Bar->new();
$foo->print_name();

Here is what has changed:

  1. I've removed the use of Exporter. It is not necessary here -- all methods defined in a package can be called by name without its involvement.

  2. The new method on WWW::Foo sets an account_name key on the object it's creating, rather than on the package itself. (Setting this on the package would mean that all objects had the same value here, making them rather useless.)

  3. The WWW::Foo::Bar object now uses the base package to inherit from WWW::Foo.

  4. The WWW::Foo::Bar::print_name method is now fleshed out. We can access the account_name key on the object to get the name. (This could also be written as a single line print "Hello $self->{account_name}\n", but that would be less clear.)

  5. The main package is declared. (This is just for simplicity. You don't need this if you're writing each package in its own file.)

  6. We instantiate WWW::Foo::Bar rather than WWW::Foo, as we need the method that's defined on the child class. (If we instantiated the parent class WWW::Foo, it would not support this method.)

  7. We don't use indirect method calls for new. Indirect method calls are bad.

  8. We call $foo->print_name() to call the method.

Your 'Child' example includes this line:

our %EXPORT_TAGS = ( 'all' => [ qw( new ) ] );

which will export a function called 'new' and won't export any other functions (e.g.: print_name).

However exporting functions is kind of 'old school' and something I almost never do in my Perl code any more. In particular, if you're writing object oriented code (which you seem to be), you don't need to export anything, as the constructor will be called explicitly via the class name and all other methods are called via the object, so Perl know which package to find them in.

You're calling your constructor like this:

my $foo = new WWW::Foo();

It's considered better practice to avoid the 'indirect object syntax' and instead explicitly call new as a class method like this:

my $foo = WWW::Foo->new();

If you have been away from Perl for a while and want to do OO code, I'd really recommend taking a look at Moose. Moose::Manual a good starting point.

like image 32
Grant McLean Avatar answered Aug 01 '26 13:08

Grant McLean



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!