Usar la versión paramétrica da
- Más información para los usuarios de la función.
- Restringe la cantidad de programas que puede escribir (verificación de errores gratuita)
Como ejemplo aleatorio, supongamos que tenemos un método que calcula las raíces de una ecuación cuadrática
int solve(int a, int b, int c) {
// My 7th grade math teacher is laughing somewhere
}
Y luego quieres que funcione en otros tipos de números como cosas además int
. Puedes escribir algo como
Num solve(Num a, Num b, Num c){
...
}
El problema es que esto no dice lo que quieres. Dice
Dame 3 cosas que sean números (no necesariamente de la misma manera) y te devolveré algún tipo de número
¡No podemos hacer algo como int sol = solve(a, b, c)
if a
,, b
y c
are int
s porque no sabemos que el método devolverá int
al final! Esto lleva a un baile incómodo con abatimiento y oración si queremos usar la solución en una expresión más amplia.
Dentro de la función, alguien podría entregarnos un float, un bigint y grados, y tendríamos que sumarlos y multiplicarlos. Nos gustaría rechazar estáticamente esto porque las operaciones entre estas 3 clases van a ser un galimatías. Los grados son mod 360, por lo que no será el caso a.plus(b) = b.plus(a)
y surgirán hilaridades similares.
Si usamos el polimorfismo paramétrico con subtipado, podemos descartar todo esto porque nuestro tipo realmente dice lo que queremos decir
<T : Num> T solve(T a, T b, T c)
O en palabras "Si me das algún tipo que sea un número, puedo resolver ecuaciones con esos coeficientes".
Esto aparece en muchos otros lugares también. Otra fuente buena de ejemplos son funciones que abstracto sobre algún tipo de contenedor, ala reverse
, sort
, map
, etc.