toSsortingng (), equals () et hashCode () dans une interface

Donc, j’ai une interface avec un tas de méthodes qui doivent être implémentées, les noms de méthodes ne sont pas pertinents.

Les objects qui implémentent cette interface sont souvent placés dans des collections et ont également un format spécial toSsortingng () que je souhaite utiliser.

Donc, j’ai pensé qu’il serait commode de mettre hashCode (), equals () et toSsortingng () dans l’interface, pour s’assurer que je me souvienne de remplacer la méthode par défaut pour ces derniers. Mais quand j’ai ajouté ces méthodes à l’interface, l’EDI / Comstackr ne se plaint pas si je n’ai pas implémenté ces trois méthodes, même si je les place explicitement dans l’interface.

Pourquoi cela ne sera-t-il pas appliqué pour moi? Il se plaint si je ne mets en œuvre aucune des autres méthodes, mais il ne les applique pas. Ce qui donne? Des indices?

Tous les objects en Java héritent de java.lang.Object et Object fournissent des implémentations par défaut de ces méthodes.

Si votre interface contient d’autres méthodes, Java se plaindra si vous n’implémentez pas complètement l’interface en fournissant une implémentation de ces méthodes. Mais dans le cas de equals() , hashCode() et toSsortingng() (ainsi que quelques autres que vous n’avez pas mentionnés), l’implémentation existe déjà.

Une façon de réaliser ce que vous voulez est de fournir une méthode différente dans l’interface, par exemple toPrettySsortingng() ou quelque chose du genre. Ensuite, vous pouvez appeler cette méthode à la place de la toSsortingng() par défaut.

Il semble que vous souhaitiez forcer vos classes à remplacer les implémentations par défaut de ces méthodes. Si c’est le cas, la manière de le faire est de déclarer une superclasse abstraite dont les méthodes sont déclarées comme abstraites. Par exemple:

 public abstract class MyBaseClass implements ... /* existing interface(s) */ { public abstract boolean equals(Object other); public abstract int hashCode(); public abstract Ssortingng toSsortingng(); } 

Puis changez vos classes actuelles pour extend cette classe.

Cette approche fonctionne plutôt bien, mais ce n’est pas la solution idéale.

  • Cela peut être problématique pour une hiérarchie de classes existante.

  • Il est déconseillé de forcer les classes implémentant votre interface existante à étendre une classe abstraite spécifique. Par exemple, vous pouvez modifier les parameters dans les signatures de méthode pour utiliser la classe abstraite plutôt que les interfaces existantes. Mais le résultat final est un code moins flexible. (Et les gens peuvent trouver des moyens de subvertir cela de toute façon, par exemple en ajoutant leur propre sous-classe abstraite qui “implémente” les méthodes avec un appel super.(...) !)

  • L’imposition d’une hiérarchie de classes / d’un modèle d’implémentation particulier est à courte vue. Vous ne pouvez pas prédire si une modification future des exigences signifiera que vos ressortingctions entraînent des difficultés. (C’est pourquoi les gens recommandent une programmation par rapport aux interfaces plutôt que des classes spécifiques.)


Revenons à votre question sur la raison pour laquelle votre interface ne force pas une classe à redéclarer ces méthodes:

Pourquoi cela ne sera-t-il pas appliqué pour moi? Il se plaint si je ne mets en œuvre aucune des autres méthodes, mais il ne les applique pas. Ce qui donne? Des indices?

Une interface impose la contrainte qu’une classe concrète qui l’implémente a une implémentation pour chacune des méthodes. Cependant, il ne nécessite pas que la classe ellemême implémente ces méthodes. Les implémentations de méthode peuvent être héritées d’une super-classe. Et dans ce cas, c’est ce qui se passe. Les méthodes héritées de java.lang.Object saftisfont la contrainte.

JLS 8.1.5 indique ce qui suit:

“A moins que la classe déclarée ne soit abstraite, toutes les méthodes abstraites de chaque superinterface directe doivent être implémentées (§8.8.8.1) soit par une déclaration dans cette classe, soit par une déclaration de méthode existante héritée de la superclasse directe ou directe , car une classe qui n’est pas abstraite n’est pas autorisée à avoir des méthodes abstraites (§8.1.1.1). “

Ces trois méthodes sont définies par java.lang.Object qui est (implicitement) étendu par toutes les autres classes; par conséquent, les implémentations par défaut de ces méthodes existent et le compilateur n’a rien à redire.

Toute classe qui implémente votre interface étend également Object. Object définit hashCode, equals et toSsortingng et possède les implémentations par défaut des trois.

Ce que vous essayez d’atteindre est bon, mais pas praticable.

Il y a une implémentation pour ces méthodes venant d’ Object .

Si vous voulez forcer la substitution de equals () et hashCode (), étendez-vous à partir d’une superclasse abstraite, qui définit ces méthodes comme abstraites.

Votre object contient déjà des implémentations de ces trois méthodes, car chaque object hérite de ces méthodes d’Object, sauf si elles sont remplacées.

Java ne veut que que les méthodes soient définies quelque part. L’interface ne vous oblige pas à redéfinir les méthodes des nouvelles classes qui héritent de l’interface pour la première fois si elles sont déjà définies. Comme java.lang.Object implémente déjà ces méthodes, vos nouveaux objects sont conformes à l’interface même s’ils ne remplacent pas eux-mêmes ces trois méthodes.

D’autres personnes ont suffisamment répondu à votre question. En ce qui concerne votre problème particulier, vous pouvez envisager de créer vos propres méthodes (getSsortingngRepresentation, getCustomHashcode et equalsObject, par exemple). Vos objects étendent une classe de base dont les méthodes equals, toSsortingng et hashCode appellent ces méthodes.

Cela pourrait toutefois aller à l’encontre de l’utilisation d’une interface en premier lieu. C’est l’une des raisons pour lesquelles certaines personnes ont suggéré qu’equals, toSsortingng et hashCode n’auraient jamais dû être inclus dans la classe Object.

Adam vous donne la raison pour laquelle vous ne pouvez pas vous en sortir en essayant de forcer les égaux, hashCode et toSsortingng. J’irais pour l’implémentation suivante qui touche la solution fournie par Adam et Stephan:

 public interface Distinct { boolean checkEquals(Object other); int hash(); } public interface Ssortingngable { Ssortingng asSsortingng(); } public abstract class DistinctSsortingngableObject { @Override public final boolean equals(Object other) { return checkEquals(); } @Override public final int hashCode() { return hash(); } @Override public final Ssortingng toSsortingng() { return asSsortingng(); } } 

Désormais, toute classe qui se veut nettement distincte et représentée en tant que chaîne peut étendre le DistinctSsortingngableObject qui forcera l’implémentation de checkEquals, hashCode et toSsortingng.

Exemple de classe de béton:

 public abstract class MyDistinctSsortingngableObject extends DistinctSsortingngableObject { @Override public final boolean checkEquals(Object other) { ... } @Override public final int hash() { ... } @Override public final Ssortingng asSsortingng() { ... } } 

Les classes abstraites ne fonctionneront pas si vous avez un petit-fils puisque son père a déjà pris le dessus sur les méthodes égales et les méthodes hashCode et que vous avez encore un problème.

Essayez d’utiliser les annotations et APT ( http://docs.oracle.com/javase/1.5.0/docs/guide/apt/GettingStarted.html ) pour le faire.

Eh bien, si vous avez déclaré une interface dans laquelle toutes les méthodes sont par défaut abstraites et que vous devez fournir la fonctionnalité, mais quand vous l’implémentez dans la sous-classe, alors vous devez fournir la bonne implémentation. comme vous pouvez le voir, chaque classe est la sous-classe d’une super-classe (put simply Object est la super-classe de toutes les classes) donc si vous avez une classe implémentant une interface, vous devez fournir une implémentation pour les méthodes. mais il faut se souvenir d’une chose ici.

Indépendamment de, si vous n’avez pas déclaré ces méthodes dans l’interface, vous aviez toujours ce comportement pour la sous-classe qui implémentait l’interface en premier lieu.

donc si ne le déclarez pas, il sera toujours présent et une autre chose est que puisque ces méthodes et autres méthodes de la classe Object sont présentes pour tous les objects des classes, il n’y a donc pas besoin d’implémentation.