OK. I have a problem trying to inherit constants set in a parent class for any of the child classes.
#!/usr/bin/perl
use strict;
use warnings;
package Car;
use Exporter qw( import );
our @EXPORT_OK = ( 'WHEELS', 'WINGS' );
use constant WHEELS => 4;
use constant WINGS => 0;
sub new {
my ( $class, %args ) = @_;
my $self = {
doors => $args{doors},
colour => $args{colour},
wheels => WHEELS,
wings => WINGS,
};
bless $self, $class;
return $self;
}
package Car::Sports;
use base qw( Car );
sub new {
my ( $class, %args ) = @_;
my $self = {
doors => $args{doors},
engine => $args{engine},
wheels => WHEELS,
wings => WINGS,
};
bless $self, $class;
return $self;
}
package main;
my $obj = Car->new( doors => 4, colour => "red" );
print Dumper $obj;
my $obj2 = Car::Sports->new( doors => 5, engine => "V8" );
print Dumper $obj2;
__END__
The error is:
Bareword "WHEELS" not allowed while "strict subs" in use at ./t.pl line 30.
Bareword "WINGS" not allowed while "strict subs" in use at ./t.pl line 30.
Execution of ./t.pl aborted due to compilation errors.
Now, I haven’t come here to post without doing some research. I understand that one option would be to use Car qw( WHEELS WINGS) in Car::Sports. However, if I do that I get the following error, because the classes are all inline in the same file:
Can't locate Car.pm in @INC
For a variety of reasons, I need to keep my packages in one file. Is there a way around this? As constants are basically just subs, why do I have to import them when the same would not be true for a normal method?
Finally, I also know I can do this:
package Car::Sports;
use base qw( Car );
sub new {
my ( $class, %args ) = @_;
my $self = {
doors => $args{doors},
engine => $args{engine},
wheels => Car::WHEELS,
wings => Car::WINGS,
};
bless $self, $class;
return $self;
}
And it’s fine… But I have a number of classes and want to make the inheritance of constants more generic that having to name the parent class explicitly (and sometimes it’s not just the parent class, but the grandparent).
Many thanks in advance for any pointers!
Cheers
One workaround is to include the line
AND use the sigils in the
Car::Sportsconstructor:Your
Carclass isn’t defining its@EXPORTS_OKlist until run-time. The sigils are required because theCar::Sportsconstructor is parsed at compile-time, and the compiler doesn’t know there should beWHEELSandWINGSsymbols in theCar::Sportsnamespace.The only way to avoid the sigils is to define
Car‘s exports at compile-time:You could also avoid these machinations by defining the
Carclass in its ownCar.pmfile. Then you would just sayand everything in the
Car.pmfile would be parsed at compile time, AND theExporter::importmethod (triggered by a call toCar::import) would automatically get run and import the desired symbols to your current namespace.