Austin Hastings writes: > > So what you want is a role whose names are private to the role, not the > > aggreagating class. Well, I believe private (i.e. $:foo) variables do > > that anyway, so you can just abstract your messages out into a role and > > it will work fine. But if you read on, I'll offer some unsolicited > > design advice. > > Hmm. No. I want a role whose methods are available in the composing > class, as shown. Variables (members) don't have roles: Roles (may) > have variables.
Right, and those variables in turn become part of the *composing class. Unless they're private. > Saying "class Session does MessageList" means that MessageList may > impose member variables on Session, and will provide methods to > Session. Roles are composition, not aggregation. Whoops, got my vocabulary backwards. Trust me, we're on the same page here. > > > One solution is to compose member objects that implement this behavior: > > > > > > if ($my_object.messages.have_messages) {...} > > > > > > But that sucks. > > > > Why? From a design perspective, that's the correct way to do it. What > > if you have a routine that operates on message lists -- pruning them or > > somesuch. If you do it by renaming the methods, you break any kind of > > future-proof code reuse that abstracting gets you in the first place. > > You've got it backwards: saying $my_object.messages.have_messages is > exposing the fact that the have_messages functionality is implemented > via a member data item, instead of querying the $my_object directly. This was in my "unsolicited design advice" section, where I was proclaiming that it should be. > > But this isn't an OO design list, it's a language design list. > > And "how to make the names more readable" isn't "how to parameterize > member/method names". Okay, so you want to use a role to integrate a behavior, but with PHPly slightly different method names. You've given your brain time, and after a few beers, it still decides it wants to do this. Well, you'll be spending a lot of time hacking around, while someone else with an equally insane idea has come up with a simple solution without using roles: class MessageList { method have_messages() {...} method get_messages() {...} method add_message($msg) {...} method clear_messages() {...} } class Session { has $:messages handles /_messages?$/; has $:errors handles (s/_error(s?)$/_message$1/); } > > > > If it turns out that role private variables leak, I might suggest making > > a MessageList class as above, then making a role that knows how to turn > > a MessageList into a set of methods. Then you'd pass the role the > > MessageList object which you instantiate yourself, and it would generate > > the methods for you. That's kind of a kludge, but you're using roles > > for something they're not really intended for, so that's what you get. > > Keep in mind that there are plenty of other ways to do what you want; > > this is Perl, after all. > > Hmm. Why is this not what roles are intended for? I have identified a > packageable, reusable behavior that I want to insert into a class > using some mechanism other than inheritance. I could have sworn that > was the whole point of roles. > > In this particular case, however, I've gone one step beyond and > identified a "generic" behavior, that I'd like to implement multiple > times with slightly different names. And it's that last part that roles weren't intended for. A role is like a Java interface[1] in that it provides a set of names that other users can count on being there. If you ask for PHPly, slightly modified names then there's no set of names that the role provides. Now it's just providing implementations, and you're providing the names. That sounds much more like delegation to me. Or insanity. Luke [1] Except, because it can provide as well as require methods, it turns out to be useful.