in reply to How to do multiple inheritance?

My solution would to be to put a new wrapper in the second class and then invoke my constructor using that method. There is nothing holy about 'new'. It is just a method that is expected to perform as a constructor.

Update: In re-reading your request, it appears that you are implying that you might be overlapping method names more than just 'new'. Obviously, the inheritance model will look at the left-most class first. If you need derived classes to use a method that refers to a method of the same name as one found in class one, perhaps the wrapper needs to be in the class joining the two (or more) base classes, redirecting to the appropriate base method.

Replies are listed 'Best First'.
Re^2: How to do multiple inheritance?
by perl-diddler (Chaplain) on Sep 18, 2007 at 02:00 UTC
    Understand what you are saying about overlapping names -- that's not really my _current_ issue (though that has come up a few times during development as I create "Objects" that act as layers upon earlier objects (like "ratings" in lower, base classes just is an accessor, but updating "ratings" in a "higher" (more derived) class will also trigger some other actions (like the DB layer has a flag that gets marked "dirty").

    No..it's more like... well (please note...I'm still in process of converting to classes, so they may not be "optimally" thought out).

    I wanted to "objectify" the GUI routines so it would be easier, later to swap to another GUI, but the GUI isn't referenced until the upper level display routines -- but some of the GUI routines need to reference / refer to the keyboard-event handler and the kybd-ev-handler needs to not only make possible changes in the GUI state, but also in the lower-level data structure -- like calling the "DB" file-io level (in case of keyboard input to "save", for example).

    So "part" of my problem is that the objects are not strictly hierarchical, but need to call up & down the "object chain".

    The other part -- lets say if "main" calls and wants to access a GUI routine to add user name to frame on "main_win_handle". So main needs to know that the "handle" (not sure I like that term, but is descriptive...it's a Blessed pointer but I wouldn't call it just a pointer, but it *seems* (I may have the wrong impression, but it seems...) that the "general order of business" (business meaning deriving objects from more base objects which themselves are derived, etc...), given my readings that some attention is given to being careful not-to-create derived objects with the same field names as base objects (**unless you deliberately want that**). There seems to be some minor amount of education aimed at watching out for overlapping names and some suggested methods for avoiding collisions: example -- one method suggested prefixing public members with the package name so same-name vars from different level packages won't accidentally step on each other.

    FWIW: I'm just using 'new' because it is customary .. not because I think it special, just like people often use "$self" to refer to the "blessed pointer-handle thingy" (:-)) that's passed into a method call (where I, instead, gravitate toward "$s").

    The general structures, _often_ seem to use an anonymous assoc. array to store object data -- so I'm seeing progs organized like:

    { package Mostest_Basest_Class; sub new(){ my $self = {}; $self->{'__datum0'}=(...); $self->{'__datum1'}=(...); $self->{'__datum2'}=(...); bless $self, (Mostest_Basest_Class); return $self; } # this is the "handle" I referred to # i.e. a blessed pointer to data&methods (the +object). # (stating what appears to be "the obvious" :- +)) #accessors sub datum0 (){} # return or set datum0 sub datum1 (){} # return or set datum1 sub datum2 (){} # return or set datum2 } #end package M_B_C { package Derived1; our @ISA=qw(Mostest_Basest_Class); sub constructor1(){ my $self = Mostest_Basest_Class->new([params]) $self->{'__Derived1_datum1'} = (...); $self->{'__Derived1_datum2'} = (...); return bless(ed) $self.... } sub datum1($x){..SUPER::datum1($x)...} # overrides base class but + calls its method sub Derived1_datum2(...){...} } { package Derived2; our @ISA=qw(Derived1); sub new{ my $s=Derived1->constructor1(...) ($s->{'__Derived2_datum1'}, $s-{'_Derived2_datum2'}) = (... , ...) +; return bless $self,...; } sub Derived2_datum1(){} #no overlap sub datum2(){ ...;SUPER::datum2();...} #override calls "Mostest_Basest's but ca +lls it } { package Derived3; our @ISA=qw(Derived2); sub new{ my $s=Derived2->new(...) # previous class ($s->{'__Derived3_datum1'}, $s->{'_Derived3_datum2'}) = (... , ... +); return bless $self, ...} sub Derived3_datum1(){}... sub Derived3_datum2(){}... } # and "so on" where higher classes call constructor of lower class ============== but then ==== { package Base2_GUI; sub new(){ my $s = {}; $s->{'__datum_A'}=(...); $s->{'__datum_B'}= (...); return bless $s, $class; return $self; } sub GUI_datum_A (){} sub GUI_datum_B (){} for $sub in qw(init_GUI make_window refresh_window relabel_window) { #use GUI's "make_sub" to create other subs make_sub($sub); } } # now Derived4 uses both Derived3 AND Base2... { package Derived4; our @ISA=qw(Derived3 Base2); sub new() { my $s = Derived3->new(...); $s->{'__Derived4_datum1'}=(...)' $s->datum2(init-set); #calls Derived2's override method bless $s, $class; #need handle for Base2_GUI, but can't store in "$s", so need field + to #store it in; use local "$w" for window reference my $w=$s->{'__Derived4_Base2_GUI_handle'}=Base2_GUI->new(); $w->init_GUI(); $w->make_window(...) return $s; } sub Derived4_datum1 (){ return [or set] shift->{'_Derived4_datum1'}'; } sub re_init_GUI(){ my ($s=shift)->{'__Derived4_Base2_GUI_handle'}->init_GUI(); $s->{'__Derived4_Base2_GUI_handle'}->make_window(); } } #end package Derived4 { package User; our @ISA=qw(Derived4); sub new(){ my $c=shift; return bless Derived4->new(), ref $c || $c; } sub Do_Stuff(){ my $s=shift; my $dat0 = $s->datum0; # (pulls value from Mostest_Basest...) my $dat1 = $s->datum1; # (pulls value from Derived1) my $dat2 = $s->datum2(myval); # sets datum2 via "Derived2" { # then problems...next statement should "blow up" $s->relabel_window("$dat1, $dat2, $dat3"); $s->refresh_windows(); # also must blow up } return; } }
    That's the problem -- "User" is blind to Derived4's internal structure and doesn't know that the "window" routines would need to be called through the internally stored 2nd 'new' (constructor). I can't return BOTH handles to two separate objects, so "$s" really won't access methods in "Derived4's" 2nd base class (Base2) -- *correctly*. Perl may call Base2_GUI's methods because of the @ISA(?), but it will try to pass the "$s" value as a handle instead of the "$w" value ($s->{'__Derived4_Base2_GUI_handle'}) that Base2_GUI will be expecting.

    The following would also be incorrect to substitute for the extra-indented code above:

    { # also won't work (if privacy enforced) my $w=$s->{'__Derived4_Base2_GUI_handle'}; $w->relabel_window("..."); $w->refresh_windows("...); }
    even if it did work -- since "User" shouldn't know about Derived4's internal values.

    UG!....(hope this was more clear; just that it was *so* blasted long to type in...*sigh*) :-)
    Linda