8
votes

Méthode d'acceptation d'un objet de classe ou d'un autre objet de classe

J'ai deux méthodes telles que celles suivantes

private List<Long> getIds(String name, List<T> objects) {
    List<Long> ids = new ArrayList<>();
    for (T object : objects) {
        if (object.getName().equals(name)) ids.add(object.getId());
    }
    return ids;
}


2 commentaires

faire une interface animal contenant getname. mettre en œuvre cela dans le chat et le chien. Dans votre méthode Getids, changez-vous? étend son animal


Vous voudrez peut-être aussi consulter ce Recette de davon en tapant de Wikipedia ...


7 Réponses :


0
votes

Vous devez utiliser une API de réflexion, si vous ne pouvez pas modifier les classes de chat et de chien. Sinon, utilisez l'animal d'interface (ou la coulée de type)


1 commentaires

Dans le cas où une super-classe n'est pas possible, je pense que c'est le seul moyen. Mais comme il se trouve, ce n'est pas beaucoup plus qu'un commentaire. Pourriez-vous ajouter du code?



1
votes

Vous devez définir une interface commune pour chat et chien , par exemple animal . .

que vous pouvez passer une liste comme paramètre.


5 commentaires

OP dit Ici Cat and Dog est des classes Java intégrées. En conséquence, je ne peux pas effectuer l'héritage et fournir un animal de super classe pour eux avec nom et identifiant comme variables de données.


Je modifie ma réponse pour vous montrer une autre approche possible


@Vinayveluri ah .. j'ai raté de voir ça


Salut .. je sais une sorte de cette approche .. Mais j'aimerais éviter de changer de chat ou de classe de chien.


John, regarde ma solution de réflexion. J'espère que ça va aider



1
votes

Pouvez-vous simplement faire une interface pour le chien et le chat? XXX PRE>

Ensuite, votre méthode deviendrait P>

public class Log4jEvent extends EventWrapper {
    LoggingEvent event;

    public Log4jEvent(LoggingEvent event) {
        this.event = event;
    }

    @Override
    public String getFormattedMessage() {
        if (event.getMessage() != null) {
            return event.getMessage().toString();
        } else {
            return null;
        }
    }
}


4 commentaires

Je ne peux pas faire ça. Je ne peux pas éditer les cours de chat ou de chien


Je l'ai vu, vous pouvez simplement les envelopper dans votre classe d'enveloppe personnalisée. Bien..Je ajouter un échantillon de mon expérience.


@ 이승진 intéressant. créant ainsi de nouvelles classes extension des classes de chat et de chien et de mettre en œuvre l'interface animal?


J'ai posté un exemple de mon expérience, très similaire à l'affaire de l'auteur.



0
votes

La solution la plus facile à laquelle je puisse penser (maintenir l'héritage de côté) vérifie si l'objet est de type chien ou chat. Voici le code de la méthode: -

private List getIds(String name, List objects) {
    List<Long> ids = new ArrayList<>();

    for (Object obj : objects) {
        if (obj instanceof Dog) {
            Dog d = (Dog) obj;
            if (d.getName().equals(name)) {
                ids.add(d.getId());
            }
        } else if (obj instanceof Cat) {
            Cat c = (Cat) obj;
            if (c.getName().equals(name)) {
                ids.add(c.getId());
            }
        }
    }
    return ids;
}


2 commentaires

Non Non Non. Cela impliquerait que je peux transmettre la liste aussi. Vaincre le but des génériques


Cela ne réduit pas du tout de la duplication de code. Vous venez de négocier deux méthodes de 7 lignes chacune pour une méthode de 18 lignes.



0
votes

Si ce n'est aucun problème avec des lignes supplémentaires dans la méthode. Qu'en est-il de cela? XXX

Une approche plus générique serait la suivante: xxx


4 commentaires

Bien que cela puisse faire le travail, cela ouvre la fonction pour passer quelque chose comme la liste des - pas vraiment des génériques


Oui, mais cela ne fournira rien de mal à d'autres types. Vous pouvez ajouter une valeur de retour nul ou une exception en cas de types inattendus.


Pas mal techniquement mais qu'en est-il de la complexité du temps .. vous finissez par itération de toute la collection entièrement juste pour renvoyer une liste vide


Pour être franc, j'essaie d'optimiser le code. Cela signifierait un code de nettoyage avec une meilleure efficacité et un nombre moins élevé de LOC. Donc, je ne préférerais pas utiliser l'instance et une deuxième approche à coup sûr.



1
votes

OK, j'ai que vous ne pouvez utiliser aucun type d'héritage. Voici une solution courte avec API de réflexion alors:

private static List<Long> getIds(String name, List<?> objects) {
    List<Long> ids = new ArrayList<>();
    for (Object object : objects) {
        try {
            Method getName = null;
            Method getId = null;

            for (Method method : object.getClass().getMethods()) {
                if (method.getName().equals("getName") && method.getReturnType().equals(String.class) && method.getParameterTypes().length == 0) {
                    getName = method;
                }
                if (method.getName().equals("getId") && method.getReturnType().equals(Long.class) && method.getParameterTypes().length == 0) {
                    getId = method;
                }
                if (getName != null && getId != null && getName.invoke(object).equals(name)) {
                   ids.add((Long) getId.invoke(object));
                   break;
                }
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }
    return ids;
}


11 commentaires

Quelques suggestions: utilisez égale pour comparer les chaînes et augmenter un illegalargumentException au cas où la classe n'a pas cet attribut. En outre, list est trop strict; Utilisez la liste .


merci pour des égaux - mon erreur, écrivit ce code trop vite)


De plus, pouvez-vous me fournir l'exemple, où toute instance de la liste d'objets d'entrée n'aurait pas accessible Méthode d'équivalence? Ça a l'air intéressant


Avec cette approche, comment puis-je savoir (si je veux appeler getids ) que les objets de la liste que je donne doivent avoir au moins deux méthodes chaîne publique getname () et Public Long Getid () ?


Vous ne pouvez pas savoir avec certitude, quelle est la liste et quelles méthodes il a. C'est pourquoi une exception "Noschmethod" peut être produite et doit être prise (voir la clause "Catch"). Je peux écrire un exemple plus softisé, mais il n'y a pas de moyen idéal pour résoudre le problème de l'auteur sans interface - vous devez effectuer des compromis pour faire face à la duplication de code dans cette situation :)


Et c'est exactement ce qui me dérange de cette solution. Il existe une solution idéale (coffre-fort), voir la réponse de TOBIAS_K.


Sa solution pour Java 8 est bonne, mais pas idéale aussi - vous devez traiter tous les groupes d'instances dans la liste d'objets d'entrée par une méthode d'appel d'approche spécifique comme: getids ("Quelqu'un", listofcats, chat :: getname, chat :: getname) ; getids ("Quelques noms", ListOfdogs, Chien :: getName, Dog :: getid); etc. Et que si nous avons une liste d'entrée de tous les objets? Non seulement les chats et les chiens - pas même des animaux. Mon appel de méthode est très simple: getids (nom, INPUTLIST_THINS)


Pour être franc, j'essaie d'optimiser le code. Cela signifierait un code de nettoyage avec une meilleure efficacité et un nombre moins élevé de LOC. L'approche que vous m'avez montré ci-dessus est assez bonne. Mais cela ne réduit pas considérablement le nombre de lignes.


J'aimerais avoir quelque chose de petit et concis comme @tobias_k's réponse, mais avec Java 7.


@Philipjohn pour être honnête, personnellement, j'irais avec cette réponse, à l'exception que je lancerais aussi un illegalargumentException au cas où la méthode ne peut pas être trouvée, au lieu d'ignorer silencieusement les éléments qui n'ont pas de méthodes. Je crains que cela soit aussi proche que possible de Typage de canard à Java


Au fait, j'ai fixé le code des exceptions nosuchmethod inutiles (peut être lent pour le traitement des listes massives) et ajouté une certaine filtration par signature de méthode (plus confiante, qu'est-ce que nous essayons exactement d'invoquer). Mais je ne sais pas le moyen de rendre ce code de réflexion plus concis dans Java 7 :( et la seule alternative - Tools de génération de code - Effectue encore pire



4
votes

Une autre possibilité: Si vous utilisez Java 8, vous pouvez transmettre les méthodes getter pour nom et identifiant comme paramètres supplémentaires dans la méthode. Ceci est sûr de type et ne nécessite ni de réflexion ni de modifications aux classes d'origine.

private List<Long> getIds(String name, List<?> objects) {
    if (objects.size() == 0) {
        return Collections.emptyList();
    }
    if (objects.get(0) instanceof Cat) {
        return getIds(name, (List<Cat>) objects, Cat::getName, Cat::getId);
    }
    if (objects.get(0) instanceof Dog) {
        ...
    }
    throw new IllegalArgumentException("List containing unsupported type!");
}


1 commentaires

C'était une très bonne approche. Mais mon projet actuel doit être à Java 7. Et le client veut que ce soit Java 7. :-)