Reputation: 46
I have the following problem, may be I am trying to solve it in a bad way so if you tell me how to do it in a right way I would be very grateful!
I have a base class which has a method which I want to access to a package variable based on real object class (ref($self)).
#!/usr/bin/env perl
my $var = SubClass->new();
$var->method();
package BaseClass;
sub new { construct... }
sub method {
my $self = shift;
# in this method I wan to get values from 'our %VAR' of the children class or ref($self) class, something like that:
return ${ref($self)::VAR}{k1};
# of course I can create a method and do it in the following way but I am not sure that it's a good idea
return $self->get_var()->{k1};
}
sub get_var { die "Imaplement in children"; }
package SubClass;
use base 'BaseClass';
our %VAR = (k1 => 'smth', k2 => 'smth', ...);
sub get_var { return \%VAR } # don't like this idea
1;
Upvotes: 0
Views: 321
Reputation: 57640
Using the %{ref($self)::VAR}
solution may sometimes be the easiest, although a paranoid programmer would include some checks:
# Accessing %__PACKAGE__::VAR:
# I hope that I'm not in a subclass,
# because that would change the value reported by `ref($self)`
# and I can't be bothered to search @ISA manually...
unless (defined ref $self) {
die "\$self is not a reference!";
}
if (ref $self ~~ [qw/SCALAR ARRAY HASH
CODE REF GLOB LVALUE FORMAT IO VSTRING Regexp /]) {
die "\$self is not an object!";
}
no strict 'refs'; # Hehe, I can't use strict here :S
unless (%{ref($self).'::VAR'}) {
warn "Umm, this hash is empty."
. "I don't know if I just created it, or it is meant to be that way.";
}
return ${ref($self).'::VAR'}{k1};
In conclusion, using an accessor method does not only save us repetition, it is also safer, less hackish and far more object oriented:
sub return_var {
# We know that we are in the right package.
# We know we are accessing the correct hash.
# It is irrelevant whether I call this method
# from the package/class or from an object.
# And I'm glad to take the method performance penalty
# in exchange for clear code.
return \%VAR;
}
In conclusion #2, there is more than one way to do it. And in Perl, there is no "right" way. Although you might understand why I find the second solution more elegant.
Upvotes: 3