Re: test case for trouble inheriting overload behavior with roles
[email protected] (Stevan Little)
| Newsgroups | perl.moose |
|---|---|
| Message-ID | <[email protected]> |
Hello, On Aug 21, 2007, at 12:29 PM, John Napiorkowski wrote: > Hi, > > Recently I was building a Role that used the overload > module to manage some simple stringify behavior when I > noticed that classes which consumed the role didn't > seem to get the overload behavior. Yes, roles do not currently support overload. > Basically the test case shows how overload works for > inheritance with plain old perl objects, moose > objects, but not for moose objects which do a role. > > I'm guessing that this would be an issue for other > modules that work similarly to overload, in that they > create stuff in import that is on the caller > namespace. So this problem might bite others at weird > times. Yes, that is correct. Class::MOP (the underlying meta-object layer that Moose sits on) does not consider a method part of a class unless the CV (code reference) declares that it is from that package. Class::MOP uses the Sub::Name module to insure that this is true, but normal perl import behavior does not do this. In most cases this is not an issue, since this type of "mixin" behavior is widely known as a hack and is usually only used in limited cases (for instance CGI::Application uses this in their "Plugin" mechanism). In addition, the whole idea of roles is what is meant to replace this hack, so the collision of these things is even more unlikely. Now, this is only partially the problem with roles and overload. > If anyone more familiar with how Roles do their job > could take a look at the test case and let me know > what they think I would appreciate it. The way roles work is to collect all the methods in the package, and then (using a strict set of method combination and conflict rules) stuff these methods into the class (or role) which is consuming it. The presents some difficulties for overload, the first being the fact that the (CV) methods imported by overload do not appear to come from the role package. The second issue being that overload does some other tricks under the covers, in particular it uses a method named "()" (yes, that is the actual name of the method) to mark that a package is using overloading. Because this method is only used internally by overload, a role should not treat this as a method conflict if it were to see the method multiple times. However, that is exactly how it would interpret it. There were some other issues, but I don't recall what they were. I found all this out the hard way when I first wrote Class::Trait. So, to make a long story short, overload support cannot be done "automatically" with roles, given to the nature of how overload.pm itself is implemented. With Class::Trait I added an $overload variable, which stored the args for overload::import, and then applied them to each package. This (or something similar) could certainly be done with roles. Of course it would require that the overloaded methods also go through the same composition/conflict rules that methods go through, and we would also need to capture "required" overloads as well in order to properly support all functionality. So it's fairly straightforward, but the implimentation is non-trivial. > I'm happy to work on this as well, just need a little > mentoring about where to start. I would be happy to point you in the right direction, but right now the role mechanism is getting a long needed refactoring. I suggest you wait until after that is complete (hopefully in the next month or so) before you try to add this feature. It will be well worth the wait since you should then be able to re-use the compsition/conflict mechanism instead of re-writing it (as you would have to do now). - Stevan