Among these three approaches, the 'extend approach is the one for which it's most important to pay attention to the order in which extensions occur in the code (or on the REPL) for efficiency and precedence purposes.
Here's my personal take on when to use 'extend vs. something else:
If there's a facility that does what you need, use it, but if there isn't, use 'extend ^_^
'extend is a hack, or rather, a tool for hacking. I mean that in a good way, I use it all the time. But pile too many hacks on top of each other and you get a mess.
So if you're extending a function in a way that can be done with generics, that's good, because now you can do your definitions in an independent order and you're not wondering what hacks are going to be messing up your hack.