clt60
clt60

Reputation: 63932

How to subclass CGI.pm to be fully workable?

Have this demo CGI script (cgi_script.pl)

use 5.014;
use warnings;
use CGI;
my $q = CGI->new();
say $q->h1( join '-', $q->multi_param('p') );
say CGI::h1('some other');

runing it as perl cgi_script.pl p=1 p=2 prints

<h1>1-2</h1>
<h1>some other</h1>

I want create My::CGI and it should do exactly everything as CGI does. For now I have:

package My::CGI;
use 5.014;
use warnings;
use base qw(CGI);  
1;

And modify the above script (my_script.pl)

use 5.014;
use warnings;
use My::CGI;

my $q = My::CGI->new();
say $q->h1( join '-', $q->multi_param('p') );
say My::CGI::h1('some other');

when running it as perl my_script.pl p=1 p=2 it prints:

<h1>1-2</h1>
Undefined subroutine &My::CGI::h1 called at my_script.pl line 7.

e.g., the object oriented interface works, but not the functions, like CGI::h1(...) and such.

The question is: How to create the My::CGI to be fully compatible with the parent CGI? e.g.

Not need code, just any pointer/idea to "how to solve correctly" the problem.

Upvotes: 0

Views: 135

Answers (2)

choroba
choroba

Reputation: 241918

Fortunately, CGI supports the :all tag:

#! /usr/bin/perl
use warnings;
use strict;

{   package MyCGI;
    use CGI qw{ :all };  # Import all functions.
    use parent 'CGI';    # Inherit the methods.
}

my $q = MyCGI->new;
print $q->h1('Title');
print MyCGI::h2('Section');

Upvotes: 3

simbabque
simbabque

Reputation: 54333

You basically gave the basis for an answer yourself. You are talking about sub_classing_. A class implies an object. Calling the functional interface of a module that provides both functional and object oriented interfaces will need extra work when inheriting.

Perl's object orientation has a few pitfalls. In general it works with the package namespaces. There is CGI, and there is My::CGI. If you say

package My::CGI;
use base 'CGI';

or

package My::CGI;
use parent 'CGI';

you tell Perl that anything that is blessed into the My::CGI namespace has CGI in its @ISA. That's the inheritance thingy.

But if you call a simple function (not a method), that is ignored. There is just the namespace.

package My::CGI;
use 5.014;
use warnings;
use base qw(CGI);  
1;

This package does not define any subs in its namespace. So you cannot call them. They are still located only in the CGI package.

You would have get them into your own namespace first.

package My::CGI;
use 5.014;
use warnings;
use base qw(CGI);  

*h1 = \&CGI::h1;

1;

Now your example call will work.

Of course that is a bit tedious. You could look into the symbol table, check out the entries and work with those to automatically create aliases for all the functional interface subs.

Upvotes: 1

Related Questions