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

hello. short version: is there an equivalent of __PACKAGE__ that will give me the name of a subclass rather than the package which immediately contains it?

er, that didn't make much sense. long version:

Class::DBI is fond of constructions like this:

package My::Actor; ... My::Actor->has_many( 'roles', 'My::Actor::Role', 'actor' );

which are normally written with __PACKAGE__ for ease of revision.

I'm consolidating a lot of shared code in a single application, which will be extendable to handle various site requirements. As part of that, I want to subclass modules like the one above, in which case I need the relationships to stick to the subclass, not the superclass.

for example, this:

package Sub::Person; use base qw(Super::Person); __PACKAGE__->has_many( 'organisations', 'Sub::Organisation', 'person' +);
package Super::Person; use base qw(Class::DBI); __PACKAGE__->table('people'); __PACKAGE__->has_many( 'sessions', 'Super::Session', 'person' ); ...

wants to define a class that inherits the session() method and database parameters from Super::Person and adds an organisations() method of its own. (has_many() defines methods that follow database relationships to return objects from the corresponding poop classes).

It works exactly as I want it to except that the has_many() defines a sessions method in Super::Person, not Sub::Person, and breaks the network of relationships. Quite reasonable of it, since __PACKAGE__ is 'Super::Person' at that point. Hence the question: how can I access the name of the current subclass while in the superclass?

But I wonder if this is even possible with class-level code like that? Any suggestions much appreciated.

thanks.

Replies are listed 'Best First'.
Re: __PACKAGE__ in subclass
by fruiture (Curate) on Oct 20, 2002 at 17:13 UTC

    I think you've got something wrong about that subclassing. The superclass doesn't know its subclasses, only the subclass knows its superclasses as they are in @ISA. The base pragma only puts a class into @ISA.

    Now, whenever a method in the subclass is called and not found there, it is searched for in all classes that stand in @ISA of that package:

    package Superclass; sub foo { print "Superclass::foo( @_ )\n" } sub bar { print "Superclass::bar( @_ )\n" } package Subclass; use base 'Superclass'; sub bar { print "Subclass::bar( @_ )\n" } package main; Subclass->foo; #Superclass::foo( Subclass ) Subclass->bar; #Subclass::bar( Subclass )

    If you make Class::DBI create a 'sessions()' method for "Super::Person" and "Sub::Person" has "Super::Person" in its @ISA, you can be sure that perl will look for 'sessions()' in "Super::Person" if it doesn't find it in "Sub::Person", but the first parameter passed to 'sessions' will be "Sub::Person". Just get rid of that __PACKAGE__, it only makes you unflexible.

    --
    http://fruiture.de

      Reading your reply, I realise that I missed out a key point. Very sorry. I was writing to the poop group too and assumed too much immersion in Class::DBI.

      __PACKAGE__->has_many( 'sessions', 'Super::Session', 'person' );

      The has_many() class method here creates two object methods: a sessions() method in this class, which returns a list of session objects, and a person() method in Super::Session, which returns a single person object. It's just a way of representing a one to many link.

      As you say, everything is fine in the class and subclass presented here: you get what you ask for according to where you ask for it.

      Where it breaks down is in the method created in the foreign class. It thinks it should return an object of Super::Person, since that was the package from which it was created, but in fact I want an object of Sub::Person, since that was the subclass which caused - but did not make - the call to has_many. grrr.

      I'm beginning to think that Class::DBI's inheritance is just broken here. Or, as you say, my thinking is broken here. Guess I need to find another way.

        I'm unsure as to what you're trying to do, but maybe the caller function would help you?

        Makeshifts last the longest.

Re: __PACKAGE__ in subclass
by Aristotle (Chancellor) on Oct 20, 2002 at 18:11 UTC
    I think you're looking for $self->method() - unless you mean something different than you appear to. What exactly is it you're trying to do?

    Makeshifts last the longest.

Re: __PACKAGE__ in subclass
by rir (Vicar) on Oct 20, 2002 at 22:10 UTC
    I am confused as to what you want also.

    I do not recommend the following. It seems wrong to embed knowledge of the subclass in a superclass. Even in languages that let you put a superclass over a class without its cooperation.

    But perhaps ref is what is needed.

    package Super; sub method { # handle dual nature methods my $class = ref( $_[0]) || $_[0]; print "In package: ", __PACKAGE__, " called from $class\n"; } package Sub; use vars qw( @ISA); @ISA= qw( Super); sub new { bless {}; } package main; my $sub = &Sub::new(); $sub->method(); Sub->method();
Re: __PACKAGE__ in subclass
by adrianh (Chancellor) on Dec 28, 2002 at 23:50 UTC