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

hi all,
maybe my qestion is dull, but since i'm not sure about the answer, i think i better let you blame me rather than doing it by myself...

imagine an inheritance tree like this one:
MotherClass / \ / \ / \ ChildClass1 ChildClass2
quite simple so far. imagine further that MotherClass provides all children with a common constructor, so that all children look somehow like:
package MotherClass::ChildClass1; use strict; use vars qw/@ISA/; use MotherClass; @ISA = qw/MotherClass/; sub new { my ($class, $args) = @_; my $self = $class->SUPER::new($args); ... }
still simple. imagine still further, that in ChildClass1 some object methods are defined, which i like to use in ChildClass2 - but that there are signifant reasons speaking against inheriting Child2 from Child1, but from the Mother instead. So, my questions are:
1.)am i right with the assumption, that inheriting ChildClass2 from both ChildClass1 and MotherClass may lead the compiler to complain about a "deep recursion"? (multiple inheritance would be the easy way of importing the methods from Child1.)
2.)since the methods i want to import into Child2's namespace are object methods, i have some doubts, whether the following construct would work:
package MotherClass::ChildClass2; use strict; use vars qw/@ISA/; use MotherClass; @ISA = qw/MotherClass/; use MotherClass::ChildClass1; ... sub object_method { MotherClass::ChildClass1::object_method(@_) }
maybe i should mention, that Child1 does not export the method.

i hope someone of you can shed some light on this (and me. :).

language is a virus from outer space.

Replies are listed 'Best First'.
Re: a question on namespaces and inheritance
by Zaxo (Archbishop) on Jun 03, 2005 at 04:01 UTC

    (1) No, I think that inheriting from both will at worst make MotherClass be checked twice in method resolution.

    (2) That should work. The fully qualified name makes export irrelevant. You can always get to a sub that way.

    It sounds like your class design still has some weak points. You want some methods of class1 in class2, but you have unspecified reasons not to inherit from class1. Perhaps the common methods should be moved into MotherClass, or else collected into a middle-level one.

    After Compline,
    Zaxo

Re: a question on namespaces and inheritance
by tlm (Prior) on Jun 03, 2005 at 03:59 UTC

    Why don't you move to MotherClass those methods from ChildClass1 that you want ChildClass2 also to have?

    You are confusing two rather different ways to use modules. Expressions like

    MotherClass::ChildClass1::object_method(@_)
    are "procedural", not OO; mixing procedural and OO calling conventions will cause you grief.

    the lowliest monk

      mixing procedural and OO calling conventions will cause you grief
      Maybe in general, but in this specific case it's entirely appropriate.

        I have to disagree. For one thing, it is hard to base an exception on the particulars of such a generic case as the one the OP presented, but more importantly, in the context of a question on inheritance, it makes no sense to me to switch over to procedural calling, which disables inheritance. If at some point someone decides to get rid of M::C1::object_method, thereby letting instances of M::C1 use M::object_method instead, then this will break M::C2::object_method as defined by the OP.

        the lowliest monk

Re: a question on namespaces and inheritance
by japhy (Canon) on Jun 03, 2005 at 03:59 UTC
    An object can call a method in any namespace by explicitly stating the namespace of that method:
    my $obj = ChildClass1->new; $obj->ChildClass2::method(...);
    In addition, classes should not "export methods". The only functions that should be exported are non-object-associated.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
      An object can call a method in any namespace by explicitly stating the namespace of that method

      Just because you can it doesn't mean it is a good idea to do so... actually, I found it rather a bad idea to call a method on an object that's not related via an is-a relation to the method package.

      The obvious solution for the OP problem is to move the common methods to the base class or to use a mixin class.

        I would disagree, if the classes are his design. If he knows the class structure, he should be able to do this confidently.

        Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
        How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: a question on namespaces and inheritance
by adrianh (Chancellor) on Jun 03, 2005 at 07:57 UTC
    imagine still further, that in ChildClass1 some object methods are defined, which i like to use in ChildClass2

    As other people have point out you can do this by giving the full name of the method involved. However I'm really sceptical that this is the right solution to the problem :-) Having to do this sort of thing is usually a sign that there is something up with the way responsibilities are distributed between the classes.

    If both classes need the same method then the most obvious thing, to me anyway, would be to put it in a common parent class.

    If you give a bit more concrete info on what the classes do and why you need to shift methods around like this we might be able to give a better solution.

Re: a question on namespaces and inheritance
by spurperl (Priest) on Jun 03, 2005 at 11:13 UTC
    If you need ChildClass2 to use stuff from ChildClass1 with your current design, I think you should reconsider it (the design).

    When you inherit Foo from Bar you say that "Foo IS-A Bar" (parrot IS-A bird). So your ChildClass1 IS-A MotherClass and ChildClass2 also IS-A MotherClass.

    Now, you say that ChildClass1 and ChildClass2 have some common functionality - and you want to express it by inheriting ChildClass2 from ChildClass1, that is, to say that ChildClass2 IS-A ChildClass1. How about just exporting the common functionality into another class and use multiple-inheritance, if there are really good reasons not to just inherit Child2 from Child1 ?

    You're giving an abstract example and it's difficult to help much. Perhaps you can provide us with the real problem at hand ? You may get more specific answers then.

      yes, you and all the others blaming me for a bad class design are right. meanwhile i found a way to avoid my difficulties. it has been, as it is so often the case with OOP, a question of dogma and reality. :)
      once again, thank you all for your comments. it's a real pleasure talking with you. :)

      language is a virus from outer space.
Re: a question on namespaces and inheritance
by thcsoft (Monk) on Jun 03, 2005 at 04:14 UTC
    thank you all very much for your profound and quick answers! :)

    @japhy:
    my $obj = ChildClass1->new; $obj->ChildClass2::method(...);
    was new to me. thx a lot!

    language is a virus from outer space.
Re: a question on namespaces and inheritance
by mugwumpjism (Hermit) on Jun 03, 2005 at 06:42 UTC

    One other way to do this is to use a mixin.

    $h=$ENV{HOME};my@q=split/\n\n/,`cat $h/.quotes`;$s="$h/." ."signature";$t=`cat $s`;print$t,"\n",$q[rand($#q)],"\n";
Re: a question on namespaces and inheritance
by GoCool (Scribe) on Jun 03, 2005 at 16:08 UTC
    A very interesting thread i must say.
    I have two questions regarding this suggestion by japhy:
    $obj->ChildClass2::method(...);

    1. What would the (implicit) first parameter to the above call be, the class name ChildClass2 or the object $obj?

    2. If the class name is being passed then thats no big deal because we could rather do this instead : ChildClass2::method(...);
    If $obj is being passed as the first parameter to the subroutine call then i don't see much use of a concept such as inheritence at all as any method from other classes can be called like this: $obj->ChildClass2::method(...); as long as you have an object to some class.

    Thanks in advance for all your answers.
      $obj.

      $obj->ChildClass2::method(...) is almost identical to ChildClass2::method($obj, ...). The only difference is that it also looks for method on ChildClass2 parent classes.

        The only difference is that it also looks for method on ChildClass2 parent classes.

        It also allows you to use SUPER:: in the method.

Re: a question on namespaces and inheritance
by nothingmuch (Priest) on Jun 04, 2005 at 22:42 UTC
    Look into Class::Trait, it's designed to solve some of these problems.

    As for the subcall, you can do it a bit more "oopishly":

    sub object_method { my $self = shift; $self->MotherClass::ChildClass1::object_method(@_); }
    which might be less confusing to read, since it looks like a method call, and not a function call.

    If you want to get the same effect as exporting, without Exporter:

    *object_method = \&MotherClass::ChildClass1::object_method;
    -nuffin
    zz zZ Z Z #!perl