2016-07-05 1 views
3

Disons que j'ai une classe sans champs, mais quelques méthodes. Par exemple, une classe qui implémente seulement une interface:Quelle est une implémentation appropriée de equals() pour une classe sans champs?

public class SomeClass implements SomeInterface 
{ 
    @Override 
    public void someMethod(int param) {...} 

    @Override 
    public int getSomeValue(OtherClass param) {return ...;} 
} 

Maintenant, je veux passer outre equals() pour cela. Puis-je toujours retourner true, en faisant valoir que "puisque les objets n'ont pas d'état, ils sont toujours égaux"?

Une mise en œuvre comme ceci:

@Override 
public boolean equals(Object other) 
{ 
    if (null == other || !(other instanceof SomeClass)) 
     return false; 
    return true; 
} 


Edit: Comme certaines personnes ont demandé à propos de l'intention derrière tout cela, je vais élaborer davantage sur le contexte dans lequel cette question a été posée:

Cette classe est un écouteur d'événements. Je l'instancie et le passe en tant qu'écouteur à une requête asynchrone, avec d'autres données, encapsulées dans un objet nommé Config. En d'autres termes, j'ai une classe nommée Config qui est composée de SomeClass et d'autres données.

public class Config 
{ 
    SomeClass someClass; 
    int otherData; 
    //... 

    @Override 
    public boolean equals(Object other) {/*???*/} 
} 

En fait, je voulais mettre en œuvre equals pour cette classe Config (Parce que je veux éviter les demandes répétées). Mais comme une partie du Config est cette instance de SomeClass je me demandais quoi faire avec ça.


question de côté: Si le SomeClass est une classe imbriquée et ont une référence implicite pour sa classe englobante, que faire alors? (Dans mon contexte, c'est le cas.)

+7

Pourquoi remplacer 'equals' du tout pour une telle classe? Vous n'allez probablement pas stocker les instances de cette classe dans un ensemble ou dans les clés d'une carte, n'est-ce pas? – Eran

+0

Je dirais qu'ils sont égaux si et seulement s'ils sont de même classe, par ex. Si j'avais 'class OtherClass extends SomeClass' et surcharger certaines méthodes, celles-ci ne devraient pas être égales. –

+0

Normalement je préconise le contraire (pour éviter les méthodes statiques), mais si une classe a des champs ** non ** quelconques; alors je me demande pourquoi vous auriez besoin de créer des instances de cette classe en premier lieu. – GhostCat

Répondre

7

Je viens de revenir true est une mauvaise mise en œuvre, car il signifie que toute instance de votre classe est égale à tout autre objet, ce qui est sans doute pas ce que vous vouliez. En outre, il va rompre equals 'contrat général de commutativité, comme mySomeClass.equals("Mousa") renverra true tandis que "Mousa".equals(mySomeClass) renverra false.

Comme SomeClass n'a pas d'état, la mise en œuvre de sa méthode equals est une question de goût. Le fait d'avoir deux instances SomeClass égales entre elles est un choix raisonnable, bien que l'implémentation que vous avez suggérée puisse être améliorée.Comme other instanceof SomeClass retournera false si other est null, la méthode pourrait juste être réécrite comme

@Override 
public boolean equals(Object other) { 
    return other instanceof SomeClass; 
} 

En outre, il faut noter que, afin de maintenir le contrat général de deux égaux objets ayant le même hashCode(), vous devriez remplacer cette méthode aussi. Par exemple:

@Override 
public int hashCode() { 
    return SomeClass.class.hashCode(); 
} 

D'autre part, il est également décider tout à fait raisonnable que depuis SomeClass n'a pas d'état, la seule façon deux objets peuvent être égaux entre eux est si les deux points à la même instance (c.-à- le comportement de l'opérateur ==). Cette approche est prise par une autre classe célèbre d'apatrides que vous connaissez peut-être du JDK - java.lang.Object.

+0

Votre hashcode échouera-t-il pour les sous-classes? – matt

+0

@matt Bon point. Utiliser 'getClass()' n'est probablement pas assez résilient. J'ai édité ma réponse pour l'améliorer. – Mureinik

+0

A propos de votre premier paragraphe, j'ai considéré que lors de mon implémentation: 'if (null == autre ||! (Autre instance de SomeClass)) return false;' – Mousa

4

C'est une question sémantique: qu'est-ce que cela signifie d'avoir deux objets de cette classe? (Serait-il même utile de l'implémenter en tant que singleton?)

S'ils peuvent être utilisés de manière interchangeable, ils peuvent en effet être considérés comme égaux. (N'oubliez pas de surcharger hashCode() puis.) Mais aussi, vous pouvez conserver la définition d'origine qui vient de Object.

+0

Je suis d'accord. Prenez un peu de recul pour un moment ... avez-vous vraiment besoin de plus d'une instance d'une classe sans état? Pourquoi mettez-vous plusieurs copies dans une collection, ou pourquoi les comparez-vous? – vikingsteve

+0

Merci, je vois ce que vous dites. En fait cela change mon point de vue et peut mieux penser. J'ai également ajouté plus d'informations sur le contexte de la question et j'aimerais avoir votre avis sur mon cas spécifique. – Mousa