Peter
Peter

Reputation: 46

accessing to the children package variable from the base class by using only $self or ref($self)

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

Answers (1)

amon
amon

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

Related Questions