UML Use Case Diagrams allow for two seemingly equivalent ways to show that a given use case might be realised in several different ways namely use case generalizations as op
An example of an extension would be an "Enter Discount Code" use case. Entering a discount code has to do with making a payment, but you don't have to enter one in order to make the payment.
You can look at the "is a" relationship to make the determination of which to use. Pay by PayPal "is a" make payment, a specific way of making a payment. Enter discount code isn't. It's something additional you can do while making a payment.
To my mind an extension is a weaker relationship than generalization as a direct substitution of the specialised use case for the base case must be possible in generalization but not necessarily in extensions.
That is true.
It seems to me that generalisation implies a polymorphic implementation is desired while extension implies some branching structure is to be used.
The diagram does not dictate any implementation. You can interpret a hint from the diagram for yourself, though. UML remains independent of language and solution there.
Isn't the Use Case stage far too early for such implementation specific concerns to be modelled?
Well, as indicated above, UML does not enforce any specific kind of implementation. However, you are gathering some important functional requirements here that might greatly influence your time schedule and workload. ("Pay with credit card" is way more complex to handle than "pay in advance by bank transfer"). So you'd strive to capture that but remain open to different solution approaches.
There are much more appropriate UML diagrams for that.
You can really use them in parallel :) as they are different views on the same subject.
Is there a hard and fast rule regarding which of the two to use and if so what is it?
I prefer the generalization in this case because in fact the extensions falsely suggest there could be a way of paying without using any of the three named options. As you indicated yourself.
When modelling with an extend relationship, the extending use case (pay via xxx) is executed when the extended use case (make payment) is at a precise location (given by the extension point, payment type) if the condition for such extend relationship holds (e.g. for "Pay via Paypal", the condition would be payment_type=PAYPAL). In this model, "Pay via Paypal" does only deals with the details of completing a payment transaction with Paypal, while "Make Payment" specifies all the behaviors that are independent of the payment method (such as computing the total amount, and saving the result of the transaction once that it was performed).
On the other hand, generalization (which is defined not only for use cases, but also for any classifier) is a broader concept, since it do not detail (at the diagram level) the details of when and how the specialized behaviors are executed. If "Pay via Paypal" were a specialization of "Make Payment" it would redefine the behavior of "Make Payment", which could be substantially different from the behavior of "Pay via credit card".
Being an extending use case does not means that the alternatives have to be hardcoded. Indeed, your first example is also a valid implementation of a extend relationship, since pd->pay(pd)
will invoke different behaviors depending on the selected payment type. Actually, use case diagram models what a system is supposed to do, while low-level implementation details are better specified in activity diagrams.