or even having behaviour that is customized per object.
I've got this in one of my production distributions. What did I do? I provided a can() method in that class that uses the same information that AUTOLOAD does. No duplication of information. It's all determined at runtime, anyways. AUTOLOAD needs to figure it out somehow based on the object, so can() should as well.
Personally, it's the module author's responsability to provide and support the implied interface that we are all accustomed to. If you do funky stuff with AUTOLOAD, then you are obligated to do the exact same funky stuff with can(). It's that simple.
I'm going to also stop in its tracks the counter-argument that UNIVERSAL::can() will be broken. Well, you know what? The only reason I can think of to call the UNIVERSAL:: version is for isa(), as a really cool version of ref(). If you're not sure if something is even an object, then why the heck are you asking if it provides a given method?!? I'm not sure I would be able to follow such obfuscation. It sure as hell better not be in my codebase cause it ain't gonna pass my code review.
(Personally, I don't like it when people call UNIVERSAL::isa(), either, cause it prevents me from doing cool things, like pretending I'm not really implemented as an ARRAY in order to fool HTML::Template into treating me like a SCALAR and stringifying me. Scalar::Utils::blessed() is a much better option, but blessed() didn't come into the core till 5.8.x. *shrugs* *makes a note to use blessed() more, now that he ranted about it*)
Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose