Lección 15 · 15 de 20
Sobrecarga de operadores · Pascal
Defina +, * y conversiones para sus propios tipos con advanced records en Free Pascal: un tipo dinero en céntimos que se suma como un número.

La directiva `{$modeswitch advancedrecords}` permite que un record tenga métodos y operadores, como una clase pequeña pero sin Create ni Free: es un valor que se copia al asignarlo. TMoney guarda el importe en céntimos enteros (Int64) para que las sumas de dinero no arrastren errores de redondeo.
Cada `class operator` enseña al compilador a usar un operador con el tipo. + suma dos TMoney y * multiplica un TMoney por una cantidad entera. Se implementan como funciones: reciben los operandos y devuelven el resultado en Result.
El más curioso es `:=`, el operador de conversión implícita: dice cómo convertir un Double en TMoney, redondeando a céntimos. Gracias a él, coffee := 1.60 funciona, y en coffee * 2 + 3.25 el 3.25 se convierte solo para poder usar el + de TMoney.
ToString es un método normal del record. `WriteStr` funciona como WriteLn pero escribe en una cadena, con el mismo formato :0:2, y no necesita la unidad SysUtils. El resultado se lee como una cuenta de cafetería: dos cafés y un pastel, 6.45 EUR.
Código · main.pas
program main;{$modeswitch advancedrecords}type TMoney = record Cents: Int64; // whole cents: no rounding surprises class operator :=(euros: Double): TMoney; class operator +(a, b: TMoney): TMoney; class operator *(a: TMoney; qty: Integer): TMoney; function ToString: String; end;class operator TMoney.:=(euros: Double): TMoney;begin Result.Cents := Round(euros * 100);end;class operator TMoney.+(a, b: TMoney): TMoney;begin Result.Cents := a.Cents + b.Cents;end;class operator TMoney.*(a: TMoney; qty: Integer): TMoney;begin Result.Cents := a.Cents * qty;end;function TMoney.ToString: String;begin WriteStr(Result, Cents / 100:0:2, ' EUR'); // like WriteLn, into a stringend;var coffee, bill: TMoney;begin coffee := 1.60; // := turns a Double into a TMoney bill := coffee * 2 + 3.25; // *, then + (3.25 is converted too) WriteLn('Coffee: ', coffee.ToString, ' (', coffee.Cents, ' cents)'); WriteLn('2 coffees + 1 cake: ', bill.ToString);end.Salida · fpc main.pas && ./main
Coffee: 1.60 EUR (160 cents) 2 coffees + 1 cake: 6.45 EUR
Para recordar
{$modeswitch advancedrecords}da métodos y operadores a los records.class operator +define qué hace+con su tipo.class operator :=define una conversión implícita.- Un record es un valor: se copia, no se crea ni se libera.
- Guarde el dinero en céntimos enteros.
Ejercicio
Añada class operator <(a, b: TMoney): Boolean y úselo para escribir si la cuenta supera los 5 EUR; después añada - para aplicar un descuento de 0.50.