Comparable Abstrat Class
Résolu/Fermé
Hurobaki
Messages postés
53
Date d'inscription
dimanche 23 mars 2014
Statut
Membre
Dernière intervention
10 mars 2017
-
9 févr. 2016 à 23:58
Hurobaki Messages postés 53 Date d'inscription dimanche 23 mars 2014 Statut Membre Dernière intervention 10 mars 2017 - 13 févr. 2016 à 19:21
Hurobaki Messages postés 53 Date d'inscription dimanche 23 mars 2014 Statut Membre Dernière intervention 10 mars 2017 - 13 févr. 2016 à 19:21
A voir également:
- Comparable Abstrat Class
- Class ram - Guide
- Nvcontainer windows class - Forum Virus
- Class 'fpdf' not found ✓ - Forum Webmastering
- Nswrtmon microsoft base class application ✓ - Forum Virus
- Rnwf msm helper class ✓ - Forum Réseaux sociaux
3 réponses
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
Modifié par KX le 10/02/2016 à 20:08
Modifié par KX le 10/02/2016 à 20:08
Bonjour,
Ton problème vient du fait que getSalaire renvoie des données random.
Donc quand l'algorithme de tri fait ses comparaisons successives il peut appeler plusieurs fois la méthode getSalaire pour le même joueur, mais ne va jamais tomber sur la même valeur. Et même s'il arrive à terminer le tri, de toute façon au moment où tu vas afficher ta liste de joueur, le toString va encore appeler la méthode getSalaire et obtenir des valeurs différentes... ça n'a pas de sens !
De plus, si tu veux implémenter Comparable<A> il faut mieux le faire dans A, parce que si tu le fais dans B extends A d'une part et dans C extends A d'autre part, tu risques d'avoir des méthodes compareTo incompatibles dans B et dans C.
Cela peut entraîner des problèmes car b.compareTo(c) calculé avec B et c.compareTo(b) calculé avec C pourraient ne pas être symétrique ce qui va faire échouer le tri.
Remarque : si Eclipse ne te demande pas explicitement d'implémenter compareTo dans Acteur c'est tout simplement parce que c'est une classe abstraite, mais ça ne t'empêche pas de le faire quand même...
Remarques :
Ton problème vient du fait que getSalaire renvoie des données random.
Donc quand l'algorithme de tri fait ses comparaisons successives il peut appeler plusieurs fois la méthode getSalaire pour le même joueur, mais ne va jamais tomber sur la même valeur. Et même s'il arrive à terminer le tri, de toute façon au moment où tu vas afficher ta liste de joueur, le toString va encore appeler la méthode getSalaire et obtenir des valeurs différentes... ça n'a pas de sens !
De plus, si tu veux implémenter Comparable<A> il faut mieux le faire dans A, parce que si tu le fais dans B extends A d'une part et dans C extends A d'autre part, tu risques d'avoir des méthodes compareTo incompatibles dans B et dans C.
Cela peut entraîner des problèmes car b.compareTo(c) calculé avec B et c.compareTo(b) calculé avec C pourraient ne pas être symétrique ce qui va faire échouer le tri.
Remarque : si Eclipse ne te demande pas explicitement d'implémenter compareTo dans Acteur c'est tout simplement parce que c'est une classe abstraite, mais ça ne t'empêche pas de le faire quand même...
public abstract class Acteur implements Comparable<Acteur> { abstract double getSalaire(); @Override public final int compareTo(Acteur another) { if (another == null) return 1; return Double.compare(getSalaire(), another.getSalaire()); } }
Remarques :
-
if(j.getClub() != this.club)
est faux, on ne doit pas comparer la valeur de deux objets avec == mais avec la méthode equals -
public void triSalaire() { Collections.sort(equipe); }
est une mauvaise manière de coder, soit tes joueurs sont toujours triés, soit jamais, dans ce cas c'est à la méthode qui fait le getJoueur() de les trier ensuite. -
DecimalFormat df = new DecimalFormat("####.##"); return ""+getPrenom()+" "+getNom()
utilises plutôt String.format, c'est plus propre (même si comme pour le tri, je doute que ce soit à la méthode toString de faire une mise en forme aussi poussée).
@Override public String toString() { return String.format("%s %s joue dans le club de %s et son salaire est de %.02f", getPrenom(), getNom(), getClub(), getSalaire()); }La confiance n'exclut pas le contrôle
Hurobaki
Messages postés
53
Date d'inscription
dimanche 23 mars 2014
Statut
Membre
Dernière intervention
10 mars 2017
Modifié par Hurobaki le 10/02/2016 à 23:02
Modifié par Hurobaki le 10/02/2016 à 23:02
Salut KX ! Décidément tu m'es d'une grande aide en ce moment !
Pour ce qui est du tri ça marche en me focalisant sur la classe mère merci de m'avoir éclairé !
J'ai corrigé les erreurs, mais j'aimerai avoir un peu plus de renseignements sur la "bonne" manière de coder par rapport au tri.
Est-ce que tu pourrais m'indiquer la méthode que tu utiliserais ?
Merci d'avance !
Pour ce qui est du tri ça marche en me focalisant sur la classe mère merci de m'avoir éclairé !
J'ai corrigé les erreurs, mais j'aimerai avoir un peu plus de renseignements sur la "bonne" manière de coder par rapport au tri.
Est-ce que tu pourrais m'indiquer la méthode que tu utiliserais ?
Merci d'avance !
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
11 févr. 2016 à 19:57
11 févr. 2016 à 19:57
De la manière dont tu as fait pour obtenir une liste triée tu es obligé de faire deux appels de méthodes :
Problème : la valeur de l'équipe est corrompue par ce tri. Il est impossible de revenir en arrière, une fois que le tri est fait, la valeur d'origine (non triée) est perdue.
Ce qui signifie que faire deux fois triSalaire() ne sert à rien. Sauf si tu a ajouté un joueur entre temps, dans ce cas il faut encore faire un triSalaire avant de récupérer les valeurs.
Ça commence à faire beaucoup de cas à envisager et finalement sans aucune garantie que lorsque tu vas récupérer la liste celle-ci sera effectivement bien triée.
Donc deux cas :
1) on considère que le tri est indispensable pour la gestion de l'équipe (ce qui n'est probablement pas pertinent dans ton cas) et dans ce cas on s'arrange pour avoir toujours une liste triée sans avoir à explicitement appeler une méthode de tri.
2) on considère que le travail de la classe Equipe n'est pas de gérer ce tri, dans ce cas on renvoie la liste des joueurs sans traitement particulier, et ce sera à la classe appelante de trier ces données comme elle le souhaite sur la copie des données qu'elle aura récupérée.
Exemples :
Equipe e; ... e.triSalaire(): List<Joueur> joueurs = e.getJoueurs();
Problème : la valeur de l'équipe est corrompue par ce tri. Il est impossible de revenir en arrière, une fois que le tri est fait, la valeur d'origine (non triée) est perdue.
Ce qui signifie que faire deux fois triSalaire() ne sert à rien. Sauf si tu a ajouté un joueur entre temps, dans ce cas il faut encore faire un triSalaire avant de récupérer les valeurs.
Ça commence à faire beaucoup de cas à envisager et finalement sans aucune garantie que lorsque tu vas récupérer la liste celle-ci sera effectivement bien triée.
Donc deux cas :
1) on considère que le tri est indispensable pour la gestion de l'équipe (ce qui n'est probablement pas pertinent dans ton cas) et dans ce cas on s'arrange pour avoir toujours une liste triée sans avoir à explicitement appeler une méthode de tri.
2) on considère que le travail de la classe Equipe n'est pas de gérer ce tri, dans ce cas on renvoie la liste des joueurs sans traitement particulier, et ce sera à la classe appelante de trier ces données comme elle le souhaite sur la copie des données qu'elle aura récupérée.
Exemples :
package test1; import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; class Player { private final String name; public Player(String name) { this.name = name; } public String getName() { return name; } public String toString() { return name; } } class Team { private final SortedSet<Player> players; public Team() { players = new TreeSet<>((p1, p2) -> p1.getName().compareTo(p2.getName())); } public void add(Player player) { players.add(player); } public SortedSet<Player> getPlayers() { return Collections.unmodifiableSortedSet(players); } public String toString() { return players.toString(); } } public class Test { public static void main(String[] args) { Team team = new Team(); team.add(new Player("xyz")); team.add(new Player("abc")); team.add(new Player("rst")); SortedSet<Player> players = team.getPlayers(); System.out.println(team); // [abc, rst, xyz] System.out.println(players); // [abc, rst, xyz] team.add(new Player("uvw")); System.out.println(team); // [abc, rst, uvw, xyz] System.out.println(players); // [abc, rst, uvw, xyz] players.add(new Player("ijk")); // UnsupportedOperationException } }
package test2; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; class Player { private final String name; public Player(String name) { this.name = name; } public String getName() { return name; } public String toString() { return name; } } class Team { private final List<Player> players; public Team() { players = new ArrayList<>(); } public void add(Player player) { players.add(player); } public List<Player> getPlayers() { return Collections.unmodifiableList(players); } public String toString() { return players.toString(); } } public class Test { public static void main(String[] args) { Team team = new Team(); team.add(new Player("xyz")); team.add(new Player("abc")); team.add(new Player("rst")); List<Player> players = team.getPlayers(); System.out.println(team); // [xyz, abc, rst] System.out.println(players); // [xyz, abc, rst] SortedSet<Player> sorted = new TreeSet<>((p1, p2) -> p1.getName().compareTo(p2.getName())); sorted.addAll(players); System.out.println(sorted); // [abc, rst, xyz] team.add(new Player("uvw")); System.out.println(team); // [xyz, abc, rst, uvw] System.out.println(players); // [xyz, abc, rst, uvw] System.out.println(sorted); // [abc, rst, xyz] } }
Hurobaki
Messages postés
53
Date d'inscription
dimanche 23 mars 2014
Statut
Membre
Dernière intervention
10 mars 2017
11 févr. 2016 à 22:27
11 févr. 2016 à 22:27
Bonsoir KX,
Merci pour ta réponse, d'après ce que je vois il faut créer une liste qui servira au triage et à être afficher sans pour autant modifier l'attribut de la classe.
Il est vrai que cela me paraît plus propre au niveau du code. J'ai juste un soucis, Collections.unmodfiableList est un méthode permettant de ne pas modifier la liste retourner c'est ça ?
Merci pour ta réponse, d'après ce que je vois il faut créer une liste qui servira au triage et à être afficher sans pour autant modifier l'attribut de la classe.
Il est vrai que cela me paraît plus propre au niveau du code. J'ai juste un soucis, Collections.unmodfiableList est un méthode permettant de ne pas modifier la liste retourner c'est ça ?
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
12 févr. 2016 à 19:41
12 févr. 2016 à 19:41
En effet, ce qui est retourné n'est pas modifiable (d'où le nom).
Cela garantie que seule la classe Team puisse modifier sa liste de Player, en aucun cas une liste interne à une classe ne doit pouvoir être modifiée part autre chose que les méthodes de cette classe. Ce qui ce serait possible si tu faisais :
Dans ce cas, il est tout à fait possible de faire
Par contre, ce que renvoie unmodifiableList ce n'est pas une copie de la liste de Team à un instant donné (on pourrait le faire). C'est la même liste que celle de l'équipe mais avec des méthodes en moins. Ainsi, lorsque l'on modifie l'objet team, les modifications sont également visibles dans la liste players.
Dans mon main c'était ces tests là :
On ajoute un joueur à l'objet team et la modification est visible dans l'objet team ET dans l'objet players. Cela fonctionnait également avec la version triée :
Cela garantie que seule la classe Team puisse modifier sa liste de Player, en aucun cas une liste interne à une classe ne doit pouvoir être modifiée part autre chose que les méthodes de cette classe. Ce qui ce serait possible si tu faisais :
public List<Player> getPlayers() { return players; }
Dans ce cas, il est tout à fait possible de faire
team.getPlayers().add("123");ce qui peut entraîner des erreurs assez importantes, par exemple on peut dépasser 11 joueurs par équipe...
Par contre, ce que renvoie unmodifiableList ce n'est pas une copie de la liste de Team à un instant donné (on pourrait le faire). C'est la même liste que celle de l'équipe mais avec des méthodes en moins. Ainsi, lorsque l'on modifie l'objet team, les modifications sont également visibles dans la liste players.
Dans mon main c'était ces tests là :
List<Player> players = team.getPlayers(); System.out.println(team); // [xyz, abc, rst] System.out.println(players); // [xyz, abc, rst] team.add(new Player("uvw")); System.out.println(team); // [xyz, abc, rst, uvw] System.out.println(players); // [xyz, abc, rst, uvw]
On ajoute un joueur à l'objet team et la modification est visible dans l'objet team ET dans l'objet players. Cela fonctionnait également avec la version triée :
SortedSet<Player> players = team.getPlayers(); System.out.println(team); // [abc, rst, xyz] System.out.println(players); // [abc, rst, xyz] team.add(new Player("uvw")); System.out.println(team); // [abc, rst, uvw, xyz] System.out.println(players); // [abc, rst, uvw, xyz]
Hurobaki
Messages postés
53
Date d'inscription
dimanche 23 mars 2014
Statut
Membre
Dernière intervention
10 mars 2017
Modifié par Hurobaki le 13/02/2016 à 19:21
Modifié par Hurobaki le 13/02/2016 à 19:21
Bonsoir KX,
J'ai refais tout mon code en m'appuyant sur ce que tu m'as dis, ainsi mon attribut liste n'est plus modifiable mis à part par les méthodes add et remove de la Collection.
Il est vrai que c'est plus propre de conserver la liste d'origine et d'effectuer les modifications sur une liste "temporaire".
Je tenais à te remercier pour le temps que tu as passer à m'expliquer et les exemples que tu as pris la peine de rédiger.
Bonne soirée à toi !
J'ai refais tout mon code en m'appuyant sur ce que tu m'as dis, ainsi mon attribut liste n'est plus modifiable mis à part par les méthodes add et remove de la Collection.
Il est vrai que c'est plus propre de conserver la liste d'origine et d'effectuer les modifications sur une liste "temporaire".
Je tenais à te remercier pour le temps que tu as passer à m'expliquer et les exemples que tu as pris la peine de rédiger.
Bonne soirée à toi !