Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

CGI::Application and object inheritance

by spork (Monk)
on Jul 27, 2005 at 14:15 UTC ( [id://478609]=perlquestion: print w/replies, xml ) Need Help??

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

Hello, I am trying to build a web application that relies on object inheritance which should theoretically be fine. The intention is to build the app around C::A, but I am running into a problem with objects that require inheritance. Whenever @ISA is invoked the program chokes. Take out @ISA (and obviously references the superclass to which it refers) and the app runs to successful (although useless) conclusion. Note the code below...

package Foo; use base 'CGI::Application'; use Bar; @ISA = ("bar"); sub cgiapp_init { my $foo = new_foo(); print "foo = $foo\n"; } sub setup { my $self = shift; $self->start_mode('mode1'); $self->run_modes( 'mode1' => 'sub1', 'mode2' => 'sub2', 'mode3' => 'sub3' ); $self->tmpl_path('/applicant'); } sub new_foo { my $class=shift; $class=ref($class)|| $class; my $foo = { stuff => '', morestuff => '', super => Bar->new() }; bless ($foo, $class); } sub sub1 { print "Show some stuff\n"; } 1;

When run as is from the command line there is an error:
"Can't locate object \"new\" via package Foo..."
When @ISA is commented out the results are the value of the $foo object (as instructed in ciapp_init()) and a bit of HTML as expected.

I have looked through the Monk archives and googled myself silly. Can someone point me in the right direction please?

Thank you

Replies are listed 'Best First'.
Re: CGI::Application and object inheritance
by cfreak (Chaplain) on Jul 27, 2005 at 14:39 UTC
    I'm not all that familiar with CGI::Application but I don't think you're doing the subclassing right. You shouldn't need @ISA at all. use base 'CGI::Application' should handle that for you. It doesn't look like you ever call the parent constructor. Here's how I would do it:
    package Foo; use base qw(CGI::Application); use Bar; sub new { my $class = shift; # SUPER refers to CGI::App because of 'use base' my $self = $class->SUPER::new(); $self->{ stuff } = 'whatever'; $self->{ bar } = Bar->new(); # I wouldn't use 'super' as a key he +re return $self; } # etc ...

    Now in your script:

    use Foo; my $app = Foo->new();

    ... should have access to all of Foo's methods and all of CGI::App's methods

      Thanks for the input cfreak. What is missing from the code sample is the actual CGI script which calls the new() defined in C::A. I am new to OO use and your answer sheds some light on where my package fits in the big picture. Thanks again.

        Ahh but it does

        In your script you just need to call:

        my $cgi_app = Foo->new();

        Sorry that wasn't clearer. new() in package Foo makes the call my $self = $class->SUPER::new(). Because of the use base statement SUPER now refers to C::A. $cgi_app is an object from which you can access your own methods or the C::A methods. If you need to pass opts to C::A you can modify new() in Foo. I'd modify it so you can pass the opts to the Foo package and it passes them on.

        Hope that makes it a bit clearer

Re: CGI::Application and object inheritance
by ikegami (Patriarch) on Jul 27, 2005 at 15:05 UTC

    As mentioned, you're overwritting the inheritance base creates. Here are three clean solution:

    use base qw( CGI::Application Bar );
    use base 'CGI::Application'; use base 'Bar';
    use CGI::Application; use Bar; our @ISA = qw( CGI::Application Bar );

    Off topic from the question at hand, are you sure you want to inherit from Bar? Inheritance ("is a") is all too often used when Encapsulation ("uses a") would be appropriate. Without knowing what Bar is, this seems to be one of those times.

      The code sample was condensed into generic form. In the real world the BAR set will be a group of common attributes and methods that will be used and extended be several FOOs. I believe this is a case of ISA, but OO use is new ground for me. Thank you for your help.
        If you're going to be creating common methods for CGI::Application, you might want to instead create a subclass Bar which inherits from C::A. Then all of your other subclasses can inherit that functionality from Bar. I did this for a C::A I wrote. This main subclass handles sessions and authentication.

        For more information on how to do this, see the C::A wiki:

        You should also look at the C::A plugins, they add functionality without having to subclass.
Re: CGI::Application and object inheritance
by sacked (Hermit) on Jul 27, 2005 at 14:30 UTC
    When you assign to @ISA, you are removing the reference to CGI::Application. Putting a print "@ISA\n" after the use base... line and then after the @ISA=... line shows the problem:
    package Foo; + use base 'CGI::Application'; print "@ISA\n"; use Bar; @ISA = ("Bar"); print "@ISA\n"; # at this point Foo only inherits from Bar __END__ CGI::Application Bar
    Rather than mixing use of use base and directly assigning to @ISA, consider the use of @ISA alone:
    use CGI::Application; use Bar; @Foo::ISA = qw(CGI::Application Bar);
    BTW, I believe "bar" should be capitalized in your original code.


      The order of your statements is deceptive. use happens at compile time, so your code actually runs them in the following order:

      package Foo; use base 'CGI::Application'; use Bar; print "@ISA\n"; @ISA = ("Bar"); print "@ISA\n";

      The first print should be wrapped in a begin to have it exected at before the use Bar.

      Same results in this case, but it's something for which one should look out, especially when demonstrating a point.

Log In?

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

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-06-23 15:09 GMT
Find Nodes?
    Voting Booth?

    No recent polls found

    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.