10 de diciembre de 2020

Tipo variable

Para rematar esta parte de fundamentos vamos a ver el tipo por referencia que nos falta que es el Tipo Variable. Lo hemos usado al utilizar interfaces como Collection o Comparable. Ahora vamos a aprender a definirlo. Como dice la documentación, el tipo variable es introducido por la declaración de un parámetro tipo en una clase, interface, método o constructor genérico.

Esto quiere decir que en nuestro código vamos a referirnos a un tipo por su identificador dentro de su ámbito (scope) pero sin definir qué tipo concreto es. Podemos aplicarle unos límites (por ejemplo decir que debe cumplir con una interface, heredar de una clase o una mezcla de ello) como veremos en la siguiente entrada.

En este caso voy a tomar como ejemplo un identificador para una clase. Puede que no tenga claro el tipo que quiero usar para identificarlo, podría ser un número, un String o cualquier otro. Al no tener claro el tipo podría verme bloqueado a no poder seguir programando, sin embargo desde que existen los tipos variables puedo hacer código genérico reutilizable para distintos tipos.

Así pues me voy a crear una interface genérica que refleje esto:

public interface Identificable<T> {

    T getId();

}

Como vemos se marca un tipo T que por defecto puede ser de cualquier tipo. La sintaxis es rodeándolo por los caracteres < y > siendo habitual usar la letra T. Si se necesitan varios parámetros de tipo habría que usar más letras (también podías usar un identificador distinto a una única mayúscula). Otros ejemplos típicos si hay que usar más de un parámetro tipo son usar R para tipos retorno, K para claves o V para valores (ver ejemplos en las interfaces funcionales de Java 8). Ahora podemos usarlo añadiendo un id a Coche. En mi caso voy a identificar los coches por la matrícula así que T sería un String. El código quedaría así:

public class Coche extends VehiculoConRuedas implements Identificable<String> {

    ...

    @Override
    public String getId() {
        return getMatricula();
    }

}

No obstante, podía plantearse escenarios muy habituales donde una matrícula no sería el identificador que se necesitaría. Podría cambiarlo rápidamente a un Long:

public class Coche extends VehiculoConRuedas implements Identificable<Long> {

    ...

    private Long id;

    @Override
    public Long getId() {
        return id;
    }

}

Como podemos observar, al cambiar la definición de T el método anteriormente implementado ya no sirve y debe devolver el nuevo tipo Long. Al ser tipos por referencia se pide que T sea un tipo por referencia, es decir, no puedo usar como tipo variable un tipo primitivo, si lo intentara me saldría un error y no compilaría.

No obstante muchas veces no sirve con dejar completamente abierto T si quiero implementar código ya que sólo podríamos contar con los miembros de Object. Por ejemplo con Collection o Comparable no pasa nada porque debe admitir todo, pero en nuestro ejemplo si quisiéramos implementar por defecto un orden natural usando T deberíamos limitarlo a un Comparable<T>. Cómo se hace lo vemos en la siguiente entrada.

No hay comentarios:

Publicar un comentario

Compárteme

Entradas populares