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

I read the responses regarding using @ISA with strict in How do I use @ISA and use strict at the same time? but still don't see an answer to the question. I am trying to build inherited objects within a single source module. The following source fails (Perl 5.8.0) as noted
use strict; use warnings; # Can't locate object method "new" via package "Test1" my $test1 = new Test1; package Test; sub new { my $proto = shift; my $class = ref($proto) || shift; my $self = {}; return bless $self, $class; } package Test1; @Test1::ISA = qw(Test);
There is no change if Test1 is
package Test1; use vars qw(@ISA); @ISA = qw(Test);

20041101 Edit by ysth: [id://] instead of <a> tag

Replies are listed 'Best First'.
Re: Revisiting strict and @ISA
by tilly (Archbishop) on Oct 29, 2004 at 21:35 UTC
    When you attempt to call the method, @ISA has not yet been assigned. You could put that line in a BEGIN{}, or have it in a separate file.

    Incidentally you messed up the my $class = ref($proto) || $proto meme. Which there are some good reasons not to use, it is better to make the method start with my $class = shift;

    A random style note. As is pointed out in Code Complete, while many different indentation/brace styles are pretty much equivalent (as long as you are consistent), there is experimental evidence indicating that comprehension is best with indents in the 2-4 range. An indent of 6 or 8 may look more attractive, but is harder to work with. Therefore I'd strongly suggest reducing how much you indent.

      Thanks for the BEGIN solution; that did the trick. Actual code uses something like
      my $case = new Case1(...); ... print $case->xml; Package Guts; sub new { ... } sub xml { return '...'; } Package Case1; BEGIN { @Case1::ISA = qw(Guts) } sub xml { my $self = shift; return '<case1>' . $self->SUPER::xml . '</case1>'; } Package Case2; BEGIN { @Case2::ISA = qw(Guts) } sub xml { my $self = shift; return '<case2>' . $self->SUPER::xml . '</case2>'; }
Re: Revisiting strict and @ISA
by chromatic (Archbishop) on Oct 29, 2004 at 21:35 UTC

    When you try to create your new Test1 object, the array assignment later in the file hasn't happened yet.

Re: Revisiting strict and @ISA
by fglock (Vicar) on Oct 29, 2004 at 21:35 UTC

    A little reordering of module declarations fixes it:

    use strict; use warnings; package Test; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; return bless $self, $class; } package Test1; @Test1::ISA = qw(Test); package Main; my $test1 = new Test1; print "isa ",ref($test1),"\n"
Re: Revisiting strict and @ISA
by diotalevi (Canon) on Oct 29, 2004 at 21:50 UTC
    Other people have given you the right answer to your question. I'd like to note that the package name 'Test' is really, really bad. There is a Test package already in the core perl distribution and you risk mixing the two, especially if another module uses the built-in Test module. You should nearly always name your modules in two or more words like 'My::Test'.
Re: Revisiting strict and @ISA
by etcshadow (Priest) on Oct 29, 2004 at 21:39 UTC
    Something that basically no-one does but practically everyone *should* do is wrap their @ISA assignments in BEGIN blocks.

    Change that to:

    package Test1; use vars qw(@ISA); BEGIN { @ISA = qw(Test); }
    And you should be just fine.
    ------------ :Wq Not an editor command: Wq
      This is also written as use base 'Parent::Class'.
      Something that basically no-one does but practically everyone *should* do is wrap their @ISA assignments in BEGIN blocks.

      I don't think that that's a valuable practice. If you want you can try to convince me. Before doing so I'd suggest reading the thread at (tye)Re: Supersplit for a fuller understanding of my views about BEGIN. (And to see that not everyone necessarily agrees with me on this.)