n many cases, an easy alternative is to create a subclass of the class you are targeting and add your new methods there.
Yet, it doesn't solve the same problem you mention as a drawback to monkey patching.
Suppose you do subclass Data::Dumper (say, to My::Data::Dumper), and define a method My::Data::Dumper::print_r, and you use instances of My::Data::Dumper instead of instances of Data::Dumper. Now, what if a new version of Data::Dumper defines a method print_r, and calls that method in an OO way? Then in instances of My::Data::Dumper, My::Data::Dumper::print_r is called instead of the expected Data::Dumper::print_r. While not getting a warning or error at compile time (which you would get when monkey-patching), it doesn't seem to be likely that this is going to work out at runtime.
What we do here is set My::AwesomeError as a superclass or Example::Error. This ensures that $error->asplode will work on Example::Error objects, but also ensures that if Example::Error ever implements its own asplode method, that one will "win".
And that's all honkey dory? Sorry, I don't see what's so good about this. Sure, you will not get a compile time error, but where you first would die with a bang if you call $error->asplode
, that's unlikely to happen once Example::Error
defines its own asplode
I don't think there's a way to defend against future name clashes, assuming one party isn't aware of your pick of names. Of the three mentioned techniques (monkey patch, sub class, super class), the monkey patch will detect the name clash at compile time. The two OO variants will just silently do the wrong thing at run time.