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

Dear Perlmonks, I have what I feel is a relatively fundamental question about Perl OO, regarding multiple inheritance: can I bless a ref into multiple packages?

The specific problem I'm trying to solve involves DBIx::Class. This ORM maps SQL table rows to instances of a class/package associated with the table. In order to achieve subclassing, one can store the additional attributes for the subclasses in the same table as the base class. Whenever a table row is retrieved, the method inflate_result() of the corresponding class is called - this method then blesses the table row (stored as a hashref) into the correct subclass (normally by looking at a specific table attribute that contains e.g. the name of the subclass).

E.g. a vehicles table containes rows that correspond to instances of the class Vehicle. A 'type' attribute could contain information about the type of vehicle and be used by Vehicle::inflate_result() to bless the vehicle row into an instances of Vehicle::Car or Vehicle::Airplane.

Now, I have a table containing entries that inherit from two base classes. These classes have subclasses, and I want to bless the table row hashref into two different subclasses, one for each base class - I have attributes like 'type1' and 'type2', not just one 'type'.

Now my question: How can I bless a hashref into two different packages? I know Perl can do multiple inheritance via the @ISA array, but I need to use bless to associate with two unrelated classes.

Replies are listed 'Best First'.
Re: Multiple Inheritance (DBIx::Class)
by Mutant (Priest) on Jun 15, 2009 at 15:45 UTC
    Sounds like you might want Moose roles. You could change the base classes you have into roles (pretty trivial), then use 'before/after/around' to modify the behaviour of the 'save' method appropriately.
Re: Multiple Inheritance (DBIx::Class)
by dsheroh (Monsignor) on Jun 15, 2009 at 16:34 UTC
    As already noted, no, you can't bless a reference into more than one class, but this sounds like it has strong potential as a use case for Moose roles. @ISA is the only form of inheritance (single or multiple) recognized by the Perl interpreter.

    Now, as for why you can't bless a reference into more than one class, you need to think about how Perl OO works in the first place:

    A Perl "object" is actually just a reference which is associated (via bless) with the namespace of a certain package. (This package is commonly referred to as a "class", but, really, it's just a namespace.) This association tells perl that any subroutines accessed by way of the blessed reference should be resolved within the connected package's namespace, passing the reference itself as the first argument. You can't be in more than one namespace at a time, therefore a reference can't be blessed into more than one "class" at a time.

    One way that you might be able to do what you're thinking about ("might" because I don't completely follow your intent) within normal Perl OO would be to access the inherited methods directly by their packages. There's not really anything special about SUPER, so if you have something that's both a Vehicle::Car and a Vehicle::Airplane, you can save it to both classes by calling both Vehicle::Car::save($self) and Vehicle::Airplane::save($self).

Re: Multiple Inheritance (DBIx::Class)
by Cybris (Sexton) on Jun 15, 2009 at 12:54 UTC
    To slightly elaborate on my problem:

    All my classes have a save() method which save the class-specific attributes to the database. Subclasses call SUPER::save() in this method and only handle their own, additional, attributes.

    Now I need a way to

    a. inherit the attributes of two different subclasses into a single class (composed of two arbitrary combinations of subclasses; e.g. a Vehicle that is a Vehicle::Car AND a Vehicle::Airplane)

    b. make a save() call to this combined subclass that calls BOTH subclasses's save() methods. This will call SUPER::save() twice, but I can live with that.

    Is there a way to do this dynamically, short of writing a package that inherits from both subclasses for every possible combination of two subclasses?
Re: Multiple Inheritance (DBIx::Class)
by Zen (Deacon) on Jun 15, 2009 at 15:39 UTC
    You'd be better off using the database to define your relationships.