Since the constants are subroutines and you can get inheritance by calling them as methods bit has been covered to death already, here is a different spin on things.
If you know you are only working in a single file, you can use lexical constants to bridge packages:
package Parent;
our ($NO_LEVEL, $MY_LEVEL, $YOUR_LEVEL);
*NO_LEVEL = \0; # this split declaration installs aliases to numbers
*MY_LEVEL = \1; # into the lexicals. since numbers are constants
*YOUR_LEVEL = \2; # to perl, the aliased names are also constants
package Child;
# just to demonstrate that anything below can access the constants
sub printAll {
print "$NO_LEVEL $MY_LEVEL $YOUR_LEVEL\n";
}
Child->printAll; # 0 1 2
eval {$NO_LEVEL = 3} or print "error: $@\n";
# error: Modification of a read-only value attempted at ...
If you don't need perl to die when assigning to the constant, the our
declaration gets a bit simpler (and could be a my
):
our ($NO_LEVEL, $MY_LEVEL, $YOUR_LEVEL) = (0, 1, 2);
You can bring back the constant nature while still using the terse syntax with a little magic:
my $constant = sub {Internals::SvREADONLY($_[$_], 1) for 0 .. $#_};
package Parent;
$constant->(our ($NO_LEVEL, $MY_LEVEL, $YOUR_LEVEL) = (0, 1, 2));
package Child;
# just to demonstrate that anything below can access the constants
sub printAll {
print "$NO_LEVEL $MY_LEVEL $YOUR_LEVEL\n"; # interpolates :)
}
Child->printAll; # 0 1 2
eval {$NO_LEVEL = 3} or print "error: $@\n";
# error: Modification of a read-only value attempted at ...
You can of course omit the $constant
coderef and inline the magic:
package Parent;
Internals::SvREADONLY($_, 1)
for our ($NO_LEVEL, $MY_LEVEL, $YOUR_LEVEL) = (0, 1, 2);