-
-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Description
Hi!
I have a class, and I want it to do two different roles, Hash::Agnostic and one of mine. Both roles have a "new" method. I have to manually resolve the conflict. I don't object to having to resolve the conflict, but I object to the idea that the .new() method role gets run in only one of those. I think there should be a better way of constructing roles so that the code in both new methods can be run. This is why I think we need an optional, more complex constructor.
Here's my idea:
method new(*@_, *%_) {
(@_, %_) = self.WALK('BUILDARGS', :roles).invoke(|@_, |%_);
my(@rvs, %rvs) = callwith(|@_, |%_);
self.WALK('DECORATE', :roles).invoke(|@_, |%_);
return(|@rvs, |%rvs);
}
This will mean that any role that does this .new() method will be able to add two extra submethods:
BUILDARGS: This gives the class a chance to modify the arguments before they're passed to the parent.new(). I'm not at all sure that the return values there will work the way I expect, but that's a detail that can be sorted outDECORATE: This gives the class a chance to do whatever initialisation it likes, but only after the parent.new()method has completed.
Note that, unlike BUILD and TWEAK, these happen for roles as well as classes.
In the case of Hash::Agnostic, I think this would mean that:
- We could either use the .new method above, or we could do a role that does it. Or we could make a new trait for roles that does it.
- We would do away with the current
.new()method, and end up with a DECORATE submethod that would contain:$self.STORE(@values, :initialize) if @values;
Thoughts?
Metadata
Metadata
Assignees
Labels
No labels