Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: How to sub class-es

by bliako (Prior)
on May 15, 2020 at 11:32 UTC ( #11116811=note: print w/replies, xml ) Need Help??


in reply to How to sub class-es

Warning: written before I saw you updated your question.

I think what you are asking is: what happens to the list of attributes in $self ( where $self is something like this: $self = {... attributes ...}; bless $self => $class;) when you have multiple inheritance and therefore multiple constructors?

There is no magic solution, but your life will be easier if the parent classes have a separate init() method to initialise, rather than initialising (i.e. filling $self with attributes - among other things) in the constructor.

This allows you to create your own $self, and then pass it to each parent class' $self->init() to be filled with that class' attributes. And then to the next parent class, etc. This, of course, requires that all parent classes use different names for attributes so that one does not overwrite attributes of the other.

That's a lot to ask. I use OOP whenever possible but only 1 in 100 times I will write a class thinking that it may be a parent in a multiple inheritance scenario (meaning: I wrote only 99 classes until now and not a single one of this flavour yet!). And only 1 in 10 I have a separate init(). (laziness, bad planning, oversight)

In other words, if the set of classes you want to do multiple inheritance from are designed with multiple inheritance in mind, then your task is easy. Just create your $self, bless it with your child class as normal and then pass it in turn to each of your parent classes' init(). More-or-less. And add them to the ISA as you say in order to inherit their methods. Which again should not overwrite each other! And if they do, then ISA order is important to determine what overwrites what.

With the above method it is very easy to introduce subtle bugs if a parent class suddenly changes a name or introduces private attributes which all of a sudden clash with other attributes and overwrite them. You will get no warning I am afraid.

So, better keep each animal to its own cage. Which is the other choice you have: what others already suggested: create different objects for each of your parent classes and store them in your current class, separately. If you want to move a leg, you do $self->leg()->move(). Which seems pretty logical and intuitive to me rather than inheriting from both a Leg and an Arm and then calling $self->move(). That is meaningless right? But perhaps your usage is different.

An addition to the above, not in my personal taste, is to hide from user the chaining of methods and allow $self->move_leg() (where sub move_leg { shift->leg()->move() }

This book (Pro Perl by Peter Wainwright) explains it well: https://books.google.com/books?id=1bbjLxkBLaMC&pg=PA760&lpg=PA760 - and helped me in writing this.

p.s. OOP is not panacea although it sounds like a good idea and in many cases it is, super really. In lot of other cases it does not come near reality and "naturality" unless you solve unsolvable dilemmas like the one faced above. Which I am sure billions of books have been written about. On the other hand, re-designing is a good tool too.

5' Edit after I read your updated question. Perhaps in your constructor you can enquire each of the "parent classes" about their methods and alias them to your own package unless there is a naming clash. Something like this - (untested) - which is what you are trying to do in AUTOLOAD(?) but it automatically finds the parent methods:

package Robo; use Class::Inspector; sub new { my $self = { Arm => new Robo::Arm(), Feet => new Robo::Feet(), }; bless $self => $class; for my $aparent (qw/Arm Feet/){ my $obj = $self->{$aparent}; for my $amethod (@{Class::Inspector->methods( $aparent, 'full', +'public' )}){ if( $self->can($amethod) ){ warn "method '$amethod' already ex +ists!!!!"; next } # this is totally pseudo-code and inject_method_into_self() # needs to be implemented but the spirit is obvious: inject_method_into_self($amethod, "new-name", sub { $self->{$a +method}->$amethod() } ); } } return $self }

bw, bliako

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://11116811]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2020-11-30 10:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?