DEV Community

Usando argumentos curingas

  • A segurança de tipos pode impedir certas construções válidas, como comparar valores absolutos de diferentes tipos numéricos.

  • Um exemplo é o método absEqual(), que verifica se dois objetos NumericFns contêm números com valores absolutos iguais, mesmo que sejam de tipos diferentes, como Double e Float.

  • O método compara o valor absoluto do objeto chamador com o do argumento passado.

NumericFns<Double> dOb = new NumericFns<Double>(1.25);
NumericFns<Float> fOb = new NumericFns<Float>(-1.25);
if(dOb.absEqual(fOb))
System.out.println("Absolute values are the same.");
else
System.out.println("Absolute values differ.");

  • Criar o método absEqual() parece simples, mas surgem problemas ao definir o parâmetro de tipo para NumericFns.

  • A dúvida está em qual tipo usar como parâmetro de NumericFns, já que ele deve lidar com diferentes tipos numéricos.

  • Uma solução inicial seria usar o mesmo tipo genérico T, mas isso pode não atender a todos os casos.

Exemplo: Example1.java
// Este código não funcionará!
// Determina se os valores absolutos de dois objetos são iguais.
boolean absEqual(NumericFns<T> ob) {
if(Math.abs(num.doubleValue()) ==
Math.abs(ob.num.doubleValue()) return true;
return false;
}

  • Usar Math.abs() para comparar valores absolutos em absEqual() só funciona se ambos os objetos NumericFns forem do mesmo tipo, como NumericFns<Integer>.

  • Essa abordagem não é genérica e impede a comparação entre diferentes tipos, como NumericFns<Integer> e NumericFns<Double>.

  • Para criar uma solução genérica, utiliza-se o argumento curinga (?), que representa um tipo desconhecido em Java.

// Determina se os valores absolutos de
// dois objetos são iguais.
boolean absEqual(NumericFns<?> ob) { // Observe o curinga.
if(Math.abs(num.doubleValue()) ==
Math.abs(ob.num.doubleValue())) return true;
return false;
}

  • NumericFns<?> permite comparar dois objetos NumericFns de qualquer tipo, tornando o método genérico.

  • Isso possibilita a comparação de valores absolutos entre objetos NumericFns com diferentes tipos numéricos.

// Usa um curinga.
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();
}
// Determina se os valores absolutos de
// dois objetos são iguais.
boolean absEqual(NumericFns<?> ob) {
if(Math.abs(num.doubleValue()) ==
Math.abs(ob.num.doubleValue())) return true;
return false;
}
// ...
}
// Demonstra um curinga.
class WildcardDemo {
public static void main(String args[]) {
NumericFns<Integer> iOb =
new NumericFns<Integer>(6);
NumericFns<Double> dOb =
new NumericFns<Double>(-6.0);
NumericFns<Long> lOb =
new NumericFns<Long>(5L);
System.out.println("Testing iOb and dOb.");
// Nesta chamada, o tipo curinga equivale a Double.
if(iOb.absEqual(dOb))
System.out.println("Absolute values are equal.");
else
System.out.println("Absolute values differ.");
System.out.println();
System.out.println("Testing iOb and lOb.");
// Nesta chamada, o curinga equivale a Long.
if(iOb.absEqual(lOb))
System.out.println("Absolute values are equal.");
else
System.out.println("Absolute values differ.");
}
}

  • Observe estas duas chamadas a absEqual( ):
    if(iOb.absEqual(dOb))
    if(iOb.absEqual(lOb))

  • Com o curinga (<?>), é possível chamar absEqual() com objetos NumericFns de tipos diferentes, como NumericFns<Integer> e NumericFns<Double>, ou NumericFns<Long>.

  • O curinga não altera os tipos permitidos para criar objetos NumericFns; isso continua sendo controlado pela cláusula extends na declaração.

  • Ele apenas permite que qualquer objeto válido de NumericFns seja usado no método.

Top comments (0)