Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Understanding module structure and inheritance

by bradcathey (Prior)
on Jan 30, 2008 at 13:19 UTC ( [id://665118]=perlquestion: print w/replies, xml ) Need Help??

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

Fellow Monasterians,

I'm trying to get my head around my directory/file structure and how code gets passed around. To experiment I have laid out the barest of an example that still works, though I normally use CGI::Application and HTML::Template, but other than the instance script, the layout can be pretty much the same.

Questions: 1) General—is this a plausible layout? 2) Specific—why do I have to include use Common.pm in my Contact.pm, when it is using Main as base and Main already includes Common.pm? Other questions: what is inheriting what? if anything? or what could be inherited? and is that even the right word? Thanks in advance.

Structure:

/public_html/---+ | | | | | calling.cgi | | /applications/---+ | | Main.pm | Common.pm | /Contact/--+ | | Contact.pm

calling.cgi

#!/usr/local/bin/perl use lib "/usr/home/bradcathey/applications/"; use strict; use Contact::Contact; print "done<br />";

Main.pm

#!/usr/bin/perl use strict; use Common; #usually CGI::Application, plug-ins, HTML::Template, etc. print "Content-type: text/html\n\n"; print "main.pm<br />"; 1;

Common.pm

package Common; use strict; use Exporter 'import'; @EXPORT = qw( show_here ); sub show_here { print "common.pm<br />"; return "thanks for contacting us"; } 1;

Contact.pm

package Main::Contact; use base qw( Main ); use Common; #why? use strict; print "contact.pm<br />"; my $msg = show_here(); print $msg."<br />"; return 1;

html output:

main.pm contact.pm common.pm thanks for contacting us done
—Brad
"The important work of moving the world forward does not wait to be done by perfect men." George Eliot

Replies are listed 'Best First'.
Re: Understanding module structure and inheritance
by jaldhar (Vicar) on Jan 30, 2008 at 14:50 UTC

    ok, let's see if I can answer this without confusing myself in the process :-)

    1. First the easy question: yes this is the kind of layout I and I would say most CGI::Application use too. It's a bit safer if your code packages or templates are not in an area accessible to the web server. However you've got some errors.

      Contact.pm should be in a directory called Main. (:: is replaced by the directory separator for your particular OS.)

      Main.pm doesn't need the shebang line but does need one which says package Main;

      In calling.cgi use Main::Contact not Contact::Contact.

    2. Internally a perl script has a table of symbols including subroutine names. These are partitioned into namespaces or "packages." Contact inherits Main. That means the Contact namespace will also include a copy of all the symbols of the Main namespace plus whatever it defines for itself. However Main.pm only imports (or 'uses') a symbol from Common.pm. That means within the symbol table for that file, there is an entry called Common::show_here. That symbol is not part of the Main:: namespace so doesn't get inherited along with other Main:: symbols in Main::Contact. However Contact.pm can still access it in its original namespace as Common::show_here. If you use Common in Contact.pm you can leave out the Common:: part and get the same result.

    Update: friedo is right and I have oversimplified far too much. What I am trying to get is that when you inherit a class that classes symbols are "yours" whereas with "use" the symbol remains "foreign" in a way though it is available to you. Hope this is clearer.

    --
    જલધર

      Contact inherits Main. That means the Contact namespace will also include a copy of all the symbols of the Main namespace plus whatever it defines for itself.

      That's actually not how inheritance works in Perl. The parent class's symbols do not get exported to the child class. When a method is called on the child class with the arrow (->) syntax, if that subroutine is not defined in the child class, then Perl searches the parent class(es) for it, and then finally tries AUTOLOAD if that doesn't work.

      Update: Fixed typo

      Great, that helps. Is there any other way to include Common.pm in Main.pm that would include the symbol for Common::show_here?

      —Brad
      "The important work of moving the world forward does not wait to be done by perfect men." George Eliot

        Well, seeing as you are using CGI::Application, see the docs about making a plugin. Most of the existing plugins are just simple wrappers around CPAN modules so you can use them as examples.

        --
        જલધર

        Hi, bradcathey,
        $ cat Common.pm package Common; use strict; use warnings; use Exporter; our @ISA = qw(Exporter); # borrows import() our @EXPORT = qw(show_here); sub show_here { } 1; $ cat Main.pm package Common; use strict; use warnings; use Common; sub show_me {} 1;
        The caller of Main.pm has direct access to show_me() and show_here() using qualified name,
        Main::show_here; # since exported by default by Common.pm Main::show_me; # originally in Main.pm
        If the caller has its own use Common then it doesn't have to qualify it, show_here() is enough.

        However, if you meant that "a way to include Common.pm in Main.pm so Contact.pm can use show_here directly, then make Main.pm to reexport the function.

        package Main; .... use Exporter; use Common; our @ISA = qw(Exporter); # borrows import() our @EXPORT = qw(show_here); # just @Common::Export to export # what ever Common exports. .... sub show_me {} 1;
        The caller,
        use Main; Main::show_me(); show_here()

        Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

Re: Understanding module structure and inheritance
by wfsp (Abbot) on Jan 30, 2008 at 14:35 UTC
    package Contact::Contact; use base qw( Main ); #use Common; #why? use strict; print "contact.pm<br />"; my $msg = Main::show_here(); print $msg."<br />"; 1;
    Main.pm imports the sub from Common.pm.
Re: Understanding module structure and inheritance
by naikonta (Curate) on Jan 30, 2008 at 18:58 UTC
    Just to add some notes....

    I hope you're not confused between package main and Main. The former is automatically provided by Perl and each Perl program are implicitly in a package main. The later is normal user-defined package name.

    Package Main::Contact indicates nothing about inheritance between Main and Contact, the double colon ("::") notation indicates physical structure where Main is the directory under which the file Contact.pm is located (it doesn't mean though that Main.pm doesnt exist).

    About the layout.... I get used to put my private Perl modules under directory lib as found in CPAN module distributions (e.g. CGI-Application-x.yy/lib/CGI/Application.pm). You may also use lib/perl as seen in the standard Perl module directories layout by the system (e.g /usr/lib/perl or /usr/lib/perl5). If there are more sibling directories (as in my case), they are all under single directory (e.g. myappl) so later I can say,

    use lib '/path/to/myappl/lib'; # or #use lib '/path/to/myappl/lib/perl'; # whichever the case
    to let Perl knows where to search for my private modules.

    Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://665118]
Approved by Joost
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (4)
As of 2024-04-18 18:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found