(Note more precise topic.)

> -----Original Message-----
> From: Aaron Sherman [mailto:[EMAIL PROTECTED]
>
> On Fri, 2004-04-30 at 17:58, Austin Hastings wrote:
>
> >   class Session
> >   {
> >     does ListOfMessages
> >          (
> >            attribute_base => 'messages',
> >            method_base    => 'messages',
> >            display_color  => 'black'
> >          );
> >
> >     does ListOfMessages
> >          (
> >            attribute_base => 'errors',
> >            method_base    => 'errors',
> >            display_color  => 'red'
> >          );
> >
> >     ...
> >   }
>
> > Can I just do:
> >
> >   role ListOfMessages($attribute_base, $method_base,
> $display_color) {...}
>
> I think you want a combination of re-dispatch and delegation:
>
>         class Session {
>               role EventHandler {
>                       # The one and only place you define the behavior
>                       method clear() {...}
>                       method add() {...}
>                       method have() {...}
>                       method get() {...}
>               }
>               class ErrorHanlder {
>                       does EventHandler;
>                       # Probably should do some funky re-dispatch thing
>                       method clear_errors() { .clear() }
>                       method add_errors() { .add() }
>                       method have_errors() { .have() }
>                       method get_errors() { .get() }
>               }
>               class MessageHanlder {
>                       does EventHandler;
>                       method clear_messages() { .clear() }
>                       method add_messages() { .add() }
>                       method have_messages() { .have() }
>                       method get_messages() { .get() }
>               }
>               has ErrorHanlder $:errors handles <<clear_errors
> add_errors have_errors get_errors>>;
>               has MessageHandler $:messages handles
> <<clear_messages add_messages have_messages get_messages>>;
>         }
>
> That should do what you want.

Well, not really:

1- It required a lot of text for little gain.
2- Most of the required text was redundant.

What I want is probably something like this:

  role ListOfMessages[$method_base]
  {
    is Array;
    handles (s/_$method_base/_messages/);

    method clear_messages() { .clear(); }
    method add_message($msg) { .push($msg); }

    method have_messages() { return .#; }
    # Isn't there a .# property for arrays?

    method get_messages() { return $_; }
  }

which is close to the same size as the original implementation, but still
doesn't speak to collision of the two lists: messages and arrays. I can move
the data declaration into the class, but this loses encapsulation:

class Session
{
  has @:messages
    does ListOfMessages«messages»;

  has @:errors
    does ListOfMessages«errors»;
}

It would be even better, of course, if the role could introspect the
variable name (assuming there is one, which isn't always true) and default
to using that for its method_base.

=Austin

Reply via email to