DEV Community

Tipos limitados

  • Os parâmetros de tipo em genéricos podem ser substituídos por qualquer classe.

  • Em alguns casos, é útil limitar os tipos que podem ser usados como parâmetro de tipo.

  • Um exemplo: criar uma classe genérica para armazenar valores numéricos e executar funções matemáticas como calcular o recíproco ou o componente fracionário.

  • A classe genérica deve permitir operar com diferentes tipos de números, como Integer, Float e Double.

  • O tipo dos números é especificado genericamente por meio de um parâmetro de tipo.

// NumericFns tenta (sem sucesso) criar uma
// classe genérica que possa executar várias
// funções numéricas, como calcular o recíproco ou o
// componente fracionário, dado qualquer tipo de número.
class NumericFns<T> {
T num;
// Passa para o construtor uma referência
// a um objeto numérico.
NumericFns(T n) {
num = n;
}
// Retorna o recíproco.
double reciprocal() {
return 1 / num.doubleValue(); // Erro!
}
// Retorna o componente fracionário.
double fraction() {
return num.doubleValue() - num.intValue(); // Erro!
}
// ...
}

  • A classe NumericFns não compila porque o compilador não reconhece métodos como doubleValue() e intValue() para o tipo genérico T.

  • Isso ocorre porque o compilador não sabe que apenas tipos numéricos deveriam ser usados como argumento para T.

  • Para resolver, é necessário limitar o tipo genérico T a classes derivadas de uma superclasse específica.

  • Em Java, isso é feito com a cláusula extends, como em <T extends superclasse>.

  • No caso de NumericFns, o problema é resolvido definindo Number como limite superior para T.

// Nesta versão de NumericFns, o argumento de
// tipo de T deve ser Number ou uma classe
// derivada de Number.
class NumericFns<T extends Number> {
T num;
// Passa para o construtor uma referência
// a um objeto numérico.
NumericFns(T n) {
num = n;
}
// Retorna o recíproco.
double reciprocal() {
return 1 / num.doubleValue();
}
// Retorna o componente fracionário.
double fraction() {
return num.doubleValue() - num.intValue();
}
// ...
}
// Demonstra NumericFns.
class BoundsDemo {
public static void main(String args[]) {
// Integer pode ser usado porque é subclasse de Number.
NumericFns<Integer> iOb =
new NumericFns<Integer>(5);
System.out.println("Reciprocal of iOb is " +
iOb.reciprocal());
System.out.println("Fractional component of iOb is " +
iOb.fraction());
System.out.println();
// Double também pode ser usado.
NumericFns<Double> dOb =
new NumericFns<Double>(5.25);
System.out.println("Reciprocal of dOb is " +
dOb.reciprocal());
System.out.println("Fractional component of dOb is " +
dOb.fraction());
// Essa parte não será compilada porque String
// não é subclasse de Number.
// NumericFns<String> strOb = new NumericFns<String>("Error");
}
}

  • Limitando o tipo genérico T com Number, o compilador garante que métodos como doubleValue() estejam disponíveis para T.

  • Essa restrição também impede a criação de objetos NumericFns com tipos não numéricos, como String.

  • Tipos limitados são úteis para garantir a compatibilidade entre parâmetros de tipo, como demonstrado na classe Pair, que armazena dois objetos compatíveis.

//Aqui, V deve ser do mesmo tipo de T ou uma subclasse de T.
class Pair<T, V extends T> {
T first;
V second;
Pair(T a, V b) {
first = a;
second = b;
}
// ...
}

  • A classe Pair usa dois parâmetros de tipo, T e V, onde V estende T.

  • Isso garante que os dois argumentos passados ao construtor de Pair sejam do mesmo tipo ou de tipos relacionados.

  • Exemplo: T pode ser uma superclasse, enquanto V é a mesma classe ou uma subclasse de T.

// Isto está certo porque T e V são Integer.
Pair<Integer, Integer> x = new Pair<Integer, Integer>(1, 2);
// Isto está certo porque Integer é uma subclasse de Number.
Pair<Number, Integer> y = new Pair<Number, Integer>(10.4, 12);

  • Não é possível ter:

// Esta linha causa um erro, porque String não é
// subclasse de Number
Pair<Number, String> z = new Pair<Number, String>(10.4, "12");

  • String não é subclasse de Number, o que viola o limite especificado por Pair.

Top comments (0)