in reply to Re: Re: Re: OOP - Sharing class methods
in thread OOP - Sharing class methods

I didn't see any mention of proxying methods off to this other class. I interpreted the question as one of how to share some common functionality, not how to pass method calls off to a different class.

Since we're doing OO and therefore concerned about inheritance and such, the utility class should be an actual class and use class methods:

package Foo; use UtilityClass; sub bubbles { ...class-specific stuff... UtilityClass->buttercup(); ...class-specific stuff... }

Replies are listed 'Best First'.
Re: Re: Re: Re: Re: OOP - Sharing class methods
by pdcawley (Hermit) on Aug 15, 2002 at 21:41 UTC
    The problem there is that you've hardwired the Utility class's name into your class. Suppose you want to subclass Foo to use a different UtilityClass (or a subclass of it), with the hardwiring you have in place you have to override all the methods that make calls to the utility class.

    At the very least you should wrap the Utility classname in a method, so your code becomes:

    package Foo; use UtilityClass; sub helper { 'UtilityClass' } sub bubbles { ... $self->helper->buttercup(); ... }
    Et voila! you'll only have to change the utility class name at two points in your subclass; no need to override.

    Actually, I wonder if you couldn't use the Exporter to implement something like a ruby mixin.

    package UtilityClass; use base 'Exporter'; @EXPORT = qw/buttercup/; sub buttercup { my $self = shift; # $self is *not* a 'UtilityClass'; ... }
    You know, I'm not sure whether that's a good idea, or a barking mad one...
      Suppose you want to subclass Foo to use a different UtilityClass

      Well, if that happened, and there was nothing else in the subclass that would cause me to override these methods, then I would do what you've suggested. However, that's a pretty unlikely scenario and I don't see any reason to add the extra complexity until it's actually needed. My opinion is that the code should stay as simple as possible until the requirements demand it be more complex.

      I've also seen this sort of technique used for runtime configuration (e.g. use Storable or Data::Dumper for serialization), but that doesn't seem to be called for here.

        Ah. I must confess that I don't really think of the first of those methods as adding complexity so much as reducing repetition and adding simplicity. I've got caught out by hardcoded class names in projects before so now it's almost a reflex to fetch them dynamically.

        Actually, my usual issue with hardcoded classnames is that it makes using 'mock object' techniques that much harder, but the very lovely Test::MockObject makes working 'round that particular issue a lot easier now.