mhacker has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm having problems with accessing class data from inherited classes. I have a base class called IDObject, which contains general database access routines for a number of tables sharing a set of properties. I then subclass IDObject to specific classes which implement functionality for specific tables in my database. The database access is handled via another class called DB, which is basically a wrapper around DBI with some extra stuff in it. The problem: I want to let my program instantiate the DB connection, and then set a class variable in the IDObject class to store the reference to the DB object in. This is done via a function called set_db() which is defined like this:
package IDObject; my $db; sub set_db { $db = shift; }
I can use the $db object without problems in the methods defined in the IDObject class. However, when I try to use it from a class that inherits from IDObject:
package Table; use DB; @ISA=qw(DB); sub fix_it { my $this = shift; my $what = shift; my $results = $db->search($what); . . }
I get error messages about not being able to execute search through and unblessed reference (I don't have the exact message here). I've tried using $SUPER::db, $this->{$db} and even $IDObject::db, but none of them works. Does anyone know how to solve this, or is this perhaps the wrong way to go about it? I know I can call my table class constructors and include the DB reference in the call. This looks ugly though, and it forces me to keep the DB reference in a global in my program.

Replies are listed 'Best First'.
Re: Class data and inheritance
by jdporter (Paladin) on Nov 07, 2002 at 14:37 UTC
    This is a classic problem, and the classical solution is to have another method in the base class which returns the $db value.

    package IDObject; my $db; sub set_db { $db = shift; } sub get_db { return $db }
    Then in the derived class you simply do this:
    sub fix_it { my $this = shift; my $what = shift; my $results = $this->get_db->search($what); . . }
      ...so you just created an access method, which is probably the best solution anyway! ++jdporter

      --
      Cheers, Joe

Re: Class data and inheritance
by broquaint (Abbot) on Nov 07, 2002 at 14:49 UTC
    Unless Table is within the same lexical scope as IDObject this won't work. If you're blessing a hashref as your object then you can just save the database handle there e.g
    # bare bones example sub new { my $class = shift; bless { dbh => $class->get_db(@_) }, $class; }
    So when Table inherits from IDObject it will use the same constructor and set the database handle.
    HTH

    _________
    broquaint

Re: Class data and inheritance
by joe++ (Friar) on Nov 07, 2002 at 14:36 UTC
    Hi mhacker,

    From your description I guess that you wrote both the base package and the derived packages. Good, because you have lots of options as described in perltooc (Perl 5.6.x or newer assumed).

    You may be interested in the section on Inheritance Concerns, but the whole doc is worth reading!

    --
    Cheers, Joe

Re: Class data and inheritance
by FamousLongAgo (Friar) on Nov 07, 2002 at 14:39 UTC
    The variable is lexically scoped, so it's not accessible from outside your class. Perhaps declaring it as a package global would do the trick?
    our $db