Lección 4 · 4 de 20
Métodos virtuales y polimorfismo · Pascal
Use virtual y override en Object Pascal para que cada clase responda a su manera a la misma llamada: polimorfismo con tarifas de envío.

Un método `virtual` puede ser sustituido por las clases hijas. TShipping.Cost calcula la tarifa normal (4.95 EUR más 0.80 por kilo), y TExpress y TPickup lo redefinen con `override`: misma firma, otro cálculo.
Dentro de un override se puede reutilizar el original: TExpress.Cost devuelve inherited Cost(kg) * 2, el doble de la tarifa normal, sin copiar la fórmula. TPickup.Cost devuelve 0, porque el cliente recoge el paquete en la tienda.
El bucle es donde aparece el polimorfismo: la variable option es de tipo TShipping, pero en cada vuelta contiene un objeto de otra clase. Como Cost es virtual, option.Cost(3.5) decide en tiempo de ejecución qué versión llamar según el objeto real, y salen tres precios distintos.
Sin virtual, el compilador elegiría por el tipo de la variable y las tres líneas costarían 7.75. El bucle recorre directamente la lista [TShipping.Create, TExpress.Create, TPickup.Create] y libera cada objeto en cuanto lo ha usado.
Es el mecanismo que mueve Lazarus: un formulario llama a Paint o Resize de cada control sin saber de qué clase es. En DMarlon Studio puede ejecutar este ejemplo con el destino Consola y la tecla F9.
Código · main.pas
program main;type TShipping = class function Cost(kg: Double): Double; virtual; end; TExpress = class(TShipping) function Cost(kg: Double): Double; override; end; TPickup = class(TShipping) function Cost(kg: Double): Double; override; end;function TShipping.Cost(kg: Double): Double;begin Result := 4.95 + 0.80 * kg; // standard rateend;function TExpress.Cost(kg: Double): Double;begin Result := inherited Cost(kg) * 2; // twice the standard rateend;function TPickup.Cost(kg: Double): Double;begin Result := 0; // collected at the shopend;var option: TShipping;begin for option in [TShipping.Create, TExpress.Create, TPickup.Create] do begin WriteLn(option.ClassName:10, ': ', option.Cost(3.5):5:2, ' EUR for 3.5 kg'); option.Free; end;end.Salida · fpc main.pas && ./main
TShipping: 7.75 EUR for 3.5 kg TExpress: 15.50 EUR for 3.5 kg TPickup: 0.00 EUR for 3.5 kg
Para recordar
virtualpermite que las hijas cambien el método;overridelo cambia.- La versión que se ejecuta depende del objeto, no de la variable.
inheriteddentro de unoverridereutiliza el original.- Una variable de la clase madre puede contener cualquier hija.
- Sin
virtual, no hay polimorfismo.
Ejercicio
Añada TInternational = class(TShipping) cuyo Cost sea la tarifa normal más 12 EUR de aduana, y métala en la lista del bucle.