8
votes

Comment faire une méthode d'instance d'interface accepter des arguments de la même classe uniquement?

Je veux utiliser une interface comme ceci: xxx

Je l'ai mise en œuvre par différents types d'objets représentant un résultat de reconnaissance vocale.

L'idée est que je souhaite comparer uniquement les résultats du même genre. C'est-à-dire que si je crée une classe intrusion implémentation résultattem , je veux que les signatures méthodes deviennent: xxx

i Sensez qu'il existe une faille de conception dans mon interface, car pour l'instant, j'utilise désormais des jeux assez laids sur les résultats du clonawithconfidence et des autres méthodes renvoyant un résultat.

Y a-t-il une meilleure façon?


4 commentaires

Que se passe-t-il si vous faites la façon dont vous postez?


@Oscarryz I pleure sur mon casting trishueux et ma vérification répétitive si (Ça.getclass (). ISInstance (item)) renvoie false; dans le est égal à Méthode des classes de mise en œuvre .


Tu ferais mieux de continuer à pleurer. Vous devez remplacer objet.equals (objet autre) pour égale Pour être utilisé pour les collections, etc. Oubliez votre version spécialisée, elle peut être plus agréable mais ne s'habitue pas n'importe où (sauf là où dit explicitement par vous). En écrivant la version spécialisée, vous risquez d'oublier d'écrire le primordial.


Il n'y a rien de mal à comparer les objets aux objets d'autres types arbitraires. Un garfield (un chat) ne devrait pas squawk lorsqu'il est demandé s'il est égal à Odie (un chien), peu importe la façon dont il pourrait ressentir. Il devrait simplement répondre que non, il n'est pas égal. Si Garfield reconnaîtrait quelque chose à quoi il est égal, alors une incapacité à reconnaître que quelque chose ne veut pas dire qu'il ne savait pas s'il était égal. Au contraire, l'incapacité de reconnaître que quelque chose aurait et en soi lui prouve qu'il n'était pas égal à celui-ci.


3 Réponses :


1
votes

Eh bien, vous pouvez le rendre générique: xxx

alors vous auriez besoin de faire Intresult implémenter résultattem . < / p>

Bien sûr, cela n'arrête pas une autre classe de mauvaise conduite, par exemple Floatresult Mise en œuvre résultattem mais il fait divers bits d'API de travail lorsque toutes les classes sont bien comportées. >


2 commentaires

Avec tout le respect due, je ne comprends pas pourquoi nous avons besoin de cette forme compliquée. Voir: Stackoverflow.com/questions/18553621/...


@Marcusjuniusbrutus: La réponse que vous avez reçue Il y a essentiellement "Non, ce n'est pas possible." Cette réponse montre ce que est possible ... Et bien que ce n'est pas parfait, ce n'est pas parfait, il permet toujours d'accueillir des API plus agréables - regardez enum pour des exemples de ceci.



11
votes

Il y a un idiome fréquemment vu qui va comme suit:

public interface ResultItem<T extends ResultItem<T>> {
    public int getConfidence();
    public boolean equals(T item);
    public T cloneWithConfidence(int newConfidence);
}

public class IntResult implements ResultItem<IntResult> {
  //...
}


9 commentaires

Toujours pas de gain de sucre syntaxique (erreur de compilateur) lorsque nous faisons ce résultatem item = nouvel intrusiontem (); INTRESULTEM IRESULTEM = Item.CloneWithConfidentialité (100);


J'étais très proche :) Je suis arrivé à peu près ceci, seulement je pensais que je ferais le crash du compilateur avec la récursion.


@aix Cette solution me donne beaucoup de problèmes. Je reçois des avertissements tout le temps maintenant lorsque vous utilisez résultatem dans une partie du code. De plus, je déclare une liste list et je ne peux pas la transmettre comme argument de type Liste . Le compilateur n'accepte pas. Une idée pourquoi?


@Dunaril 1. Concernant les avertissements, vous devez utiliser résultattem ou résultattem selon le cas. 2. Le deuxième problème n'est pas spécifique à cette solution: essayez de transmettre une liste où une liste est attendue et vous verrez la même chose comportement.


@aix merci. Y a-t-il alors une solution de contournement pour le deuxième problème?


@Dunaril Je suis sûr que quelqu'un vous suggérera une meilleure solution, mais une solution de contournement partielle pourrait être le long des lignes de Public > VOID F (liste L) {} . Ça va accepter la liste .


@Dunaril - Si vous voulez simplement lire la liste, essayez quelque chose comme Liste > .


@jtahlborn Il semble prometteur mais j'ai besoin de supprimer et d'ajouter des éléments à la liste dans l'une des méthodes.


Sauf si j'ai mal compris quelque chose que l'idiome de définition récursive proposée n'achète pas vraiment quelque chose par rapport à une forme plus simple. Voir: Stackoverflow.com/questions/18553621/...



4
votes

Pas vraiment une réponse à votre question, mais une remarque importante (je pense):

Si vous voulez que votre méthode est utilisable pour des objets de collections et similaires, vous devez mettre en œuvre Boolean Boolean Equals (Objet O) , et il devrait fonctionner pour des comparaisons à toutes sortes d'objets (dans la plupart des cas qui reviennent faux, cependant). Vous pouvez avoir en outre une méthode avec un type de paramètre plus étroit et dans les implémentations déléguées comme celle-ci: xxx

Assurez-vous de vous conformer à toutes les conditions du contrat d'égal, à savoir Symmetrie , réflexivité, transitivité et ayant une implémentation compatible HashCode.


3 commentaires

Je pense que des réponses comme celles-ci fournissent une valeur supplémentaire et sont importantes (+1)


IMHO, votre "pas vraiment une réponse" est plus précieuse que les vraies. Cependant, je recommanderais fortement la méthode supplémentaire avec un type de paramètre plus étroit.


@maaArtinus: Peut-être que la méthode supplémentaire doit être privée et nommée autre que égale , comme EqualsImpl ou tel. Il est souvent plus facile de mettre en œuvre lorsque vous n'avez pas à vérifier le bon type.