forçar implementação de equals e hashcode

Object fornece uma implementação padrão para equals e hashcode.

Estava eu aqui pensando com meus botões se existiria uma maneira de obrigar uma classe a fornecer uma implementação específica para ambos os métodos.

Não tem, né?

Não, porque os métodos não são abstratos em Object. E você também não pode torná-los abstratos em uma subclasse de Object.

Seria interessante se, por exemplo, a gente criasse uma interface, colocasse as assinaturas destes métodos na interface e, a partir daí, a implementação fosse obrigatória, né?

Você está se referindo ao C#, onde você pode indicar que um determinado método implementa EXPLICITAMENTE uma interface?

public interface IDisposable 
{
    void Dispose();
}
...
class MyClass : IDisposable 
{
    /// <summary>Implementação EXPLÍCITA de IDisposable</summary>
    public void IDisposable.Dispose () 
    {
    }
}

Não. Estou falando de java.

Foi exatamente isso que eu disse com a frase:

Com isso aí eu quis dizer que poderia ser possível criar uma interface, colocar as assinaturas dos métodos nela, e a partir daí, cada classe que implementasse esta interface seria obrigada a fornecer uma nova implementação para os métodos. O que não é possível. Obrigado.

[quote=rod.attack]Object fornece uma implementação padrão para equals e hashcode.

Estava eu aqui pensando com meus botões se existiria uma maneira de obrigar uma classe a fornecer uma implementação específica para ambos os métodos.

Não tem, né?[/quote]

Claro que tem.

A opção mais trivial é criar uma Classe super pai de todos que herda de object e da qual todas as suas classes herdam. Não todas.Apenas as que precisam de equals e hashCode implementados. Um HashableObject , por exemplo. Esta classe simplesmente define esses métodos como abstratos forçando assim a sua implementação.

Mas como usar herança é algo que só se pode fazer uma vez fica complicado controlar classes netas de HashableObject.
A opção então é usar anotações e o APT. Neste esquema o APT testa a existencia da anotação @InheritHashAndEquals que signifcia que a classe usa
as implementações da classe pai.
Sem a presença da anotação o APT procura por implementações dos métodos na classe espeficada. Se encontrar otimo, se não, lança um erro.

O APT pode ser intregado ao processo de compilação não deixando o codigo compilar se não tiver as implementações devidas.

Ferramentas menos sofisticadas não forçam a implementação, mas podem avisar quando detectarem inconsistencias, com o CheckStyle

P.S. A APT foi adicionada no java 5 mas foi depois padronizada e inserida no java 6 http://www.javabeat.net/articles/14-java-60-features-part-2-pluggable-annotation-proce-1.html

Tenho uma classe que gostaria de obrigar a implementar equals e hashcode. Se ela não fizer isso, quero que seja gerado um erro de compilação.

Tem um exemplo aí usando o APT de como isso seria feito?

[quote=rod.attack]Tenho uma classe que gostaria de obrigar a implementar equals e hashcode. Se ela não fizer isso, quero que seja gerado um erro de compilação.

Tem um exemplo aí usando o APT de como isso seria feito?[/quote]

Não. Terá que pesquisar…

Se for só uma parte das classes do sistema (por exemplo: apenas as entidades) dá para utilizar a idéia do Sérgio e criar uma classe mãe que obrigue essa implementação. Mas como ele disse, se for em todas fica complicado.

E para que a classe mãe obrigue a implementação pode ser mais ou menos assim:

abstract class Entity {
  // Sobrescreve equals
  public boolean equals(Object o) {
     // Chama o método que deve ser obrigatoriamente implementado pelas filhas
     return isEqual(o);
  }
  
  // Método de implementação obrigatória nas classes filhas
  public abstract boolean isEqual(Object o);

  /* Faz o mesmo para o hashcode */
}

[quote=sergiotaborda][quote=rod.attack]Tenho uma classe que gostaria de obrigar a implementar equals e hashcode. Se ela não fizer isso, quero que seja gerado um erro de compilação.

Tem um exemplo aí usando o APT de como isso seria feito?[/quote]

Não. Terá que pesquisar…[/quote]

Valeu. Já deu pelo menos uma ideia.

Na prática, o melhor é você usar algum plugin para a sua IDE, como o CheckStyle ou o PMD, e forçar essa regra apenas em classes de alguns subpacotes que você determinar no seu projeto. Por exemplo, classes que devam ser inseridas em hashmaps você pode deixá-las em um determinado subpacote, e então você determina uma regra para o CheckStyle verificar se hashCode e equals estão implementadas nessas classes.

vc pode verificar em runtime tb com reflection…
pode ser rapido se bem implementado (HashSet com as classes ja verificadas).