#!/usr/bin/perl
package child1;
use strict;
use warnings;
use Exporter;
use parent;
my @ISA=qw(cal Exporter);
sub new{
my $class=shift;
my $ref=cal->new();
bless ($ref,$class);
return $ref;
}
sub add{
my $ref=shift;
print "This is from child class";
my($a,$b)=@_;
return ($a+$b);
}
##parent.pm
#!/usr/bin/perl
package cal;
use strict;
use warnings;
use Exporter;
my @EXPORT=qw(add);
my @ISA=qw(Exporter EXPORT);
sub new{
my $class=shift;
my $ref=[];
bless ($ref,$class);
return $ref;
}
sub add{
my $ref=shift;
my $a=shift;
my $b=shift;
return ($a+$b);
}
1;
#!/usr/bin/perl
use strict;
use warnings;
use Exporter;
use child;
my @ISA=qw(child1 Exporter);
my $obj=new child1();
my $sum=$obj->add(1,2);
print "$sum=sum";
I am getting the error Can't locate object method "add" via package "child1" at ./test.pl line 8. I want to access the base class add method and I am getting this above error
please clarify..
The main culprit here is my @ISA
. For inheritance to work, you have to use the package @ISA
(declare it with our
).
However, there are some issues in your code beyond that:
use parent 'cal'
instead of manipulating @ISA
yourself.Exporter
.new
can be written without reblessing, because the parent's new
is inherited. The inherited new
is written in a way that already supports inheritance.parent
module already exists, and I used it in my 1st point.@ISA
must be a public package variable, not a private lexical (my
). Same for @EXPORT
. Change my
to our
on all those declarations.
Even better, depending on the version of perl
you have, simplify you life with either the parent
or base
pragma to load superclasses and to set up the class relationships.
With respect to style, you will avoid considerable confusion if you make the paths to the files that contains your modules’ code match their package names. You would do well to heed a well-established convention described in the perlmod documentation.
Module names are also capitalized unless they're functioning as pragmas; pragmas are in effect compiler directives, and are sometimes called “pragmatic modules” (or even “pragmata” if you're a classicist).
The Cal module uses an internal _initialize
method as described in the perlobj documentation to facilitate inheritance of the constructor.
See below for a complete working example.
package Cal;
use strict;
use warnings;
sub new {
my $class=shift;
my $self=[];
bless ($self,$class);
$self->_initialize();
return $self;
}
sub _initialize {}
sub add {
my $ref=shift;
my $a=shift;
my $b=shift;
print "This is from parent class\n";
return ($a+$b);
}
1;
package Child1;
use warnings;
use strict;
use v5.10.1; # when parent was added to the core
use parent "Cal";
# if you have an older perl, use base instead of parent
# use base "Cal";
sub _initialize {
my $self=shift;
push @$self, "I am a " . ref($self) . "!";
}
sub add{
my $self=shift;
my($a,$b)=@_;
print "This is from child class\n";
return ($a+$b);
}
1;
#!/usr/bin/perl
use strict;
use warnings;
use Child1;
my $obj=Child1->new();
my $sum1=$obj->add(1,2);
print "$sum1=sum1\n";
# call the add method in Cal
my $sum2=$obj->Cal::add(1,2);
print "$sum2=sum2\n";
# call add as a class method of Cal, which
# happens to work in this case because Cal::add
# does not use the instance passed to it
my $sum3=Cal->add(1,2);
print "$sum3=sum3\n";
Output:
This is from child class 3=sum1 This is from parent class 3=sum2 This is from parent class 3=sum3
The .pm modules do not need, and likely do not want, the #!/usr/bin/perl lines. This is only for programs intended to be executed from the command line, like your .pl module. While you may 'perl -cw' your .pm modules, or do other command line debugging with them, such is not normal "production" use.
And .pl modules should not have @ISA, or other "our" declarations found in packages nor any exporter related things.
As said before, change "my"s for package stuff to "our"s. The "my" hides things to outsiders as if the statements were never there.
In the "cal" class, do you want something like the following? I favor SUPER as it really shows what is going on and is much more generic.
package child1; use Exporter; our @ISA=qw(cal Exporter); sub new{ my $class=shift; my $ref=$class->SUPER::new(); return $ref; } }
One final point: you may need a "\n" on the final print statement. Without it the buffer may not flush correctly on exit in some environments so you will never see the output.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With