Tricky compareTo, herança, fácil estender - Java

5

Digamos que temos 4 classes A, B, C, D onde: A é uma superclasse de ambos B e C e C é uma superclasse de D. Suponho que, em um diagrama, deveria ser assim:

   A
 /   \
B     C
       \
        D

Além disso, a classe A implementa a interface

Comparable<A> 

e também implementa um método

public int compareTo(A another)

Eu gostaria de poder comparar cada par de objetos x, y de tal forma que eles são instâncias de classes do conjunto {A, B, C, D}. Naturalmente, eu deveria implementar um método compareTo em cada uma dessas classes, mas, por padrão, estou fazendo isso com um efeito unilateral, ou seja, definir como comparar o objeto c de C com b de B não informa nada sobre como comparar b com c. Agora, eu poderia escrever um monte de código e lidar com todos esses casos (isso também significa que eu teria que usar o método 'isInstance' para lidar com isso, certo?), Mas todas as duas classes precisam estar 'conscientes' da existência de outras. . Então, se eu quisesse adicionar outra classe, E, tal que D é uma superclasse de E, eu teria que servir todos os casos na nova classe E e além disso eu teria que mudar alguma coisa nas classes A, B, C, D a fim de "estar ciente de E".

Por isso, estou lutando para encontrar uma solução elegante, ou seja, uma que não envolva muita alteração ao adicionar uma nova classe à hierarquia. Como posso conseguir isso?

Agradeço antecipadamente por ajuda.

    
por socumbersome 03.04.2013 / 10:41
fonte

2 respostas

3

Você poderia escrever um método geral compareTo na classe A , que usa uma chave calculada pelo método compareKey que também está em A , mas pode ser substituída por cada subclasse para fazer uma distinção tão boa como quiser. Se você fizer isso retornar um float, você pode continuar subdividindo o critério de comparação sempre que um novo nível de classes herdadas for adicionado (dentro da razão, obviamente).

    
por 03.04.2013 / 10:52
fonte
1

Eu acho que o que você quer é um tipo de despacho múltiplo que é usualmente implementado em Java usando o padrão de visitante, mas você teria que mudar o código ao adicionar novas classes.

Como você realmente não precisa de envio múltiplo completo, acho que o seguinte pode ser uma boa solução. Escreva sua comparaçãoPara métodos como este: (Este é o do TestB)

@Override
public int compareTo(TestA o) {
    if(o instanceof TestB) {
        // add your code instead
        System.out.println("Compare Bs");
        return 0;
    } else {
        return super.compareTo(o);
    }
}

Como a chamada para x.compareTo é resolvida em tempo de execução, você sempre executa a função compareTo da classe mais específica. Ao verificar se o outro argumento é instanceof da classe atual, você pode detectar quando você tem que subir a hierarquia que você pode chamar super.compareTo.

Deixe-me saber se você tem alguma dúvida. :)

Edit: Eu assumi que o que você queria fazer era comparar como o ancestral comum mais específico, conforme seu comentário sobre a pergunta original.

    
por 05.04.2013 / 10:11
fonte