http://www.perlmonks.org?node_id=180942


in reply to •Re: RFC: Class::DispatchToAll
in thread RFC: Class::DispatchToAll

I just thinking about something like this just two days ago! I've had to set up a heirarchy of modules to do something very similar, but the alternate dispatch system I employed was specific to those modules and not something that you could just drop in to any other heirarchy, like this is.

The problem can be stated like this: say you want a object to try to get_money(). Say the object is a member of the classes Executive::Enron, Citizen::American and Human::AbleBodied. So you try $KenLay->get_money();. It so happens that Executive::Enron::get_money() will return a failure. However, method dispatch stops at this failure, without trying the methods in other classes. For the sake of argument, we'll call this a bad thing. (I'm speaking highly rhetorically here, ok? For a non-dark side example, consider object $YAPC, member of classes Herd::Camels and NonProfit::OfficiallyLicensed. Herd::Camels::get_money() contains 'goto &pass_hat;' but NonProfit::OfficialyLicensed::get_money() writes grant proposals.)

You can create wrapper methods or a dispatch table to explicitly call each fully-qualifed method in order, but that would be unusably brittle. You could use NEXT, but if the modules you're dealing with already exist, you'd have to rewrite all the modules (or at least the methods, in new subclasses) from the heirarchy that you are working with.

Thanks to the things I learned from Damian's Advanced Objects course (another satisfied customer!), I was able to devise a solution. But it wasn't particularly easy, and can't be simply carried over to other modules. I was just wondering if this sort of thing could be done in a portable fashion when I saw this. Thanks, domm!

-- Frag.
--
"It's beat time, it's hop time, it's monk time!"

Replies are listed 'Best First'.
•Re: Re: ?Re: RFC: Class::DispatchToAll
by merlyn (Sage) on Jul 11, 2002 at 15:26 UTC
    Again, multiple inheritance is a broken concept in general. This whole thing reeks of "bad design".

    Why would you be passing control from your derived method to a base method that might fail? You should be calling it directly, taking the results (or none), then deciding whether or not to call the next. Again, when you inherited from the multiple base classes, it's your responsibility to decide how to handle the multiple dispatch. And that's what NEXT is for.

    -- Randal L. Schwartz, Perl hacker

      I don't think I explained myself well, or else I'm not understanding your criticism. I am talking about calling a set of methods from parent classes, taking the results, and deciding whether or not to call the next. (domm's module doesn't do this checking, but it wouldn't be hard to incorporate it. In any case, in this sort of design you must take into account the possibility that all the parental methods would be invoked anyway.) It's set up so that this is only true for a given, fixed set of functions; functions that can be clearly traced back in the code. (These functions are also documented thoroughly and are vetted to be free of side-effects upon non-localized data. I agree with you about the importance of discipline in OOP.) It seems to me that this actually solves one of the major multiple inheritance headaches, by designating a method in the child class that acts as a wrapper for all of the parental methods that attempt the same function.

      Note that I misspoke in my earlier comment about wrapper methods; essentially, that's all this is, dispatch being controlled and monitored by a single method. You've got a generic wrapper method in the child class that takes the names of the parental methods that it should handle. This does not vary at run-time, but is a constant within the child class that is handling the dispatch.

      Also please note that I am not arguing that multiple inheritance is some sort of no-brainer to be used cavalierly. I am saying that I have found a particular situation where I think it makes sense. I don't question that this is a single solution to a limited set of problems.

      Finally, I have to admit that I just don't see that NEXT is always the best approach. NEXT allows each method in the parent class to make its own decisions about whether to continue dispatch or not. But it seems more natural to me, and safer, even, to have a central method oversee the process.

      -- Frag.
      --
      "It's beat time, it's hop time, it's monk time!"