Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
public:mco-2:un_projet_complet:card [2016/02/08 16:17] – [Card.java] cchatel | public:mco-2:un_projet_complet:card [2016/02/10 09:31] (Version actuelle) – fbrucker | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | ====== Classe Card ====== | ||
+ | On modélise ici une carte à jouer. On ira par touches successives en introduisant les concepts Java et Objet. Vous devriez pouvoir suivre le cours sans connaissances particulières en Java. Pour chaque notion, on renverra aux parties du tutoriel Oracle concerné. | ||
+ | |||
+ | ===== Configuration du projet ===== | ||
+ | |||
+ | On suppose que vous avez crée un nouveau projet en suivant le [[public: | ||
+ | * nouveau projet avec //Java 1.8// | ||
+ | * on choisit comme template : //Command Line Application// | ||
+ | * Package de base '' | ||
+ | |||
+ | ===== Créez des classes avec Intellij et la fenêtre projet ===== | ||
+ | |||
+ | Pour voir la fenêtre projet cliquez sur : **" | ||
+ | * cliquez sur le petit triangle à côté nom du projet, | ||
+ | * cliquez sur " | ||
+ | * vos fichiers sont rangés par package. Vous devriez donc voir une classe Main dans le package com.mco | ||
+ | |||
+ | Lorsque l' | ||
+ | |||
+ | ===== Plan ===== | ||
+ | |||
+ | |||
+ | On procèdera par touches successives : | ||
+ | * v1 : Propriétés minimales d'une carte | ||
+ | * v1.0 : uniquement les attributs et sans se soucier de packages et de visibilité. | ||
+ | * v1.1 : on règle les problèmes de visibilité (changement de package et accesseurs publics) | ||
+ | * v2 : on peut afficher à l' | ||
+ | * v3 : on remplace l' | ||
+ | * v4 : la difficile question de l' | ||
+ | * v5 : un constructeur par défaut. | ||
+ | |||
+ | |||
+ | ===== Card v1 ===== | ||
+ | |||
+ | On commence par créer une classe avec uniquement des attributs et un constructeur, | ||
+ | |||
+ | |||
+ | ==== Card v1.0 ==== | ||
+ | |||
+ | <note tip> | ||
+ | Notions vues : | ||
+ | * **[[public: | ||
+ | * **[[public: | ||
+ | * **[[public: | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | < | ||
+ | Pour créer une classe (et le fichier qui va avec) : | ||
+ | - placez vous dans le bon package en cliquant dessus dans la fenêtre projet, | ||
+ | - **" | ||
+ | |||
+ | Une fois dans le bon package on peut aussi : | ||
+ | * **" | ||
+ | * **" | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Card.java === | ||
+ | |||
+ | <code java> | ||
+ | package com.mco; | ||
+ | |||
+ | public class Card { | ||
+ | int value; | ||
+ | String color; | ||
+ | |||
+ | Card(int value, String color) { | ||
+ | this.value = value; | ||
+ | this.color = color; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | < | ||
+ | Faites du code **LISIBLE** : | ||
+ | * noms de variable explicatifs, | ||
+ | * code bien indenté (**" | ||
+ | </ | ||
+ | |||
+ | === Main.java === | ||
+ | |||
+ | On teste notre code : | ||
+ | * un code non testé est un code cassé, | ||
+ | * on va garder nos tests pour pouvoir les exécuter à chaque modification de code. | ||
+ | |||
+ | Pour la V1, les attributs de visibilité nous permettent d' | ||
+ | |||
+ | <note tip> | ||
+ | Notions vues : | ||
+ | * **[[public: | ||
+ | * **[[public: | ||
+ | </ | ||
+ | |||
+ | |||
+ | <code Java> | ||
+ | package com.mco; | ||
+ | |||
+ | public class Main { | ||
+ | |||
+ | private static void testCreationCard() { | ||
+ | Card septDeCoeur = new Card(7, " | ||
+ | |||
+ | System.out.println(septDeCoeur.value); | ||
+ | System.out.println(septDeCoeur.color); | ||
+ | } | ||
+ | |||
+ | public static void main(String[] args) { | ||
+ | testCreationCard(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Le résultat devrait être : | ||
+ | |||
+ | <code terminal> | ||
+ | 7 | ||
+ | coeur | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | Avec Intellij, ce que l'on exécute avec le menu **"run >> run"** ou le triangle vert en haut à droite de la fenêtre est déterminé par le nom à coté du triangle vert. Pour nous il devrait y avoir marqué '' | ||
+ | Pour changer ce qui est exécuté (par exemple si l'on a changé la classe Main de package) : | ||
+ | * cliquez sur le triangle pointant vers le bas à côté du texte Main | ||
+ | * cliquez sur **" | ||
+ | * vous devriez ouvrir une nouvelle fenêtre avec | ||
+ | * à gauche une liste de noms et Main en surbrillance | ||
+ | * à droite une liste d' | ||
+ | |||
+ | La ligne **" | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==== v1.1 : visibilité ==== | ||
+ | |||
+ | On utilise quelques règles : | ||
+ | * le code est placé dans des packages particuliers, | ||
+ | * les attributs sont sans modificateur (setter) mais accessibles via des accesseurs (getters), | ||
+ | * les méthodes constructeurs sont en '' | ||
+ | |||
+ | <note tip> | ||
+ | Notions vues : | ||
+ | * **[[public: | ||
+ | * **[[public: | ||
+ | * accéder aux attributs de l' | ||
+ | * design pattern : [[https:// | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Changement de package === | ||
+ | |||
+ | Changer le package de '' | ||
+ | - on change le nom du package de '' | ||
+ | - on se place sur le rouge et on clique sur l' | ||
+ | - on choisit '' | ||
+ | |||
+ | Le code ne marche plus. On le corrige avec des '' | ||
+ | |||
+ | < | ||
+ | On ne veut pas pouvoir changer la valeur de la carte une fois créée. C'est illogique en vrai et dans le code on aurait des variables '' | ||
+ | |||
+ | Lorsque l'on aura le choix on utilisera toujours des objets **non modifiables** (on dit aussi non mutables). C'est un //design pattern// (façon de faire) commun. Il s' | ||
+ | </ | ||
+ | |||
+ | === Card.java === | ||
+ | |||
+ | <code java> | ||
+ | package com.mco.battle; | ||
+ | |||
+ | public class Card { | ||
+ | int value; | ||
+ | String color; | ||
+ | |||
+ | public Card(int value, String color) { | ||
+ | this.value = value; | ||
+ | this.color = color; | ||
+ | } | ||
+ | |||
+ | public int getValue() { | ||
+ | return value; | ||
+ | } | ||
+ | |||
+ | public String getColor() { | ||
+ | return color; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Main.java === | ||
+ | |||
+ | <code java> | ||
+ | package com.mco; | ||
+ | |||
+ | import com.mco.battle.Card; | ||
+ | |||
+ | public class Main { | ||
+ | |||
+ | private static void testCreationCard() { | ||
+ | Card setDeCoeur = new Card(7, " | ||
+ | |||
+ | System.out.println(setDeCoeur.getValue()); | ||
+ | System.out.println(setDeCoeur.getColor()); | ||
+ | } | ||
+ | |||
+ | public static void main(String[] args) { | ||
+ | testCreationCard(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== v2 Affichage d'une carte à l' | ||
+ | |||
+ | Si on essaie d' | ||
+ | <code Java> | ||
+ | System.out.println(new Card(7, " | ||
+ | </ | ||
+ | |||
+ | On obtient : | ||
+ | <code terminal> | ||
+ | com.mco.battle.Card@511d50c0 | ||
+ | </ | ||
+ | |||
+ | Dès que l'on a besoin de transformer un objet en chaîne de caractères (ici la fonction '' | ||
+ | |||
+ | Comme nous n' | ||
+ | |||
+ | Pour en faire une nous-mêmes : **" | ||
+ | |||
+ | L' | ||
+ | |||
+ | <note tip> | ||
+ | Notions vues : | ||
+ | * transformer un objet en chaîne de caractères avec '' | ||
+ | * première forme d' | ||
+ | </ | ||
+ | |||
+ | === Card.java === | ||
+ | |||
+ | <code java> | ||
+ | package com.mco.battle; | ||
+ | |||
+ | public class Card { | ||
+ | int value; | ||
+ | String color; | ||
+ | |||
+ | public Card(int value, String color) { | ||
+ | this.value = value; | ||
+ | this.color = color; | ||
+ | } | ||
+ | |||
+ | public int getValue() { | ||
+ | return value; | ||
+ | } | ||
+ | |||
+ | public String getColor() { | ||
+ | return color; | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public String toString() { | ||
+ | return " | ||
+ | " | ||
+ | ", color='" | ||
+ | ' | ||
+ | } | ||
+ | } | ||
+ | </code java> | ||
+ | |||
+ | === Main.java === | ||
+ | |||
+ | <code java> | ||
+ | // snip | ||
+ | private static void testCreationCard() { | ||
+ | Card setDeCoeur = new Card(7, " | ||
+ | |||
+ | System.out.println(setDeCoeur); | ||
+ | System.out.println(setDeCoeur.getValue()); | ||
+ | System.out.println(setDeCoeur.getColor()); | ||
+ | } | ||
+ | | ||
+ | /snip | ||
+ | </ | ||
+ | |||
+ | ===== v3 : les couleurs comme une énumération ===== | ||
+ | |||
+ | Passer les valeurs et les couleurs de la carte en paramètres ne semble pas être une bonne idée ([[http:// | ||
+ | |||
+ | On va le faire ici pour les couleurs, peut-être que ce sera également utile pour les valeurs, mais nous ne le ferons pas. | ||
+ | |||
+ | <note tip> | ||
+ | Notions vues : | ||
+ | * les [[[[public: | ||
+ | * le [[http:// | ||
+ | * design pattern : [[http:// | ||
+ | * composition des toString | ||
+ | * le switch comme [[public: | ||
+ | </ | ||
+ | |||
+ | === Colors.java === | ||
+ | |||
+ | On se place dans le bon package puis **" | ||
+ | |||
+ | <code java> | ||
+ | package com.mco.battle; | ||
+ | |||
+ | public enum Colors { | ||
+ | SPADE, | ||
+ | HEART, | ||
+ | DIAMOND, | ||
+ | CLUB; | ||
+ | |||
+ | @Override | ||
+ | public String toString() { | ||
+ | switch (this) { | ||
+ | case SPADE: | ||
+ | return " | ||
+ | case HEART: | ||
+ | return " | ||
+ | case DIAMOND: | ||
+ | return " | ||
+ | case CLUB: | ||
+ | return " | ||
+ | default: | ||
+ | return " | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Card.java === | ||
+ | |||
+ | Après avoir changé le type de '' | ||
+ | |||
+ | |||
+ | <code java> | ||
+ | package com.mco.battle; | ||
+ | |||
+ | public class Card { | ||
+ | int value; | ||
+ | Colors color; | ||
+ | |||
+ | public Card(int value, Colors color) { | ||
+ | this.value = value; | ||
+ | this.color = color; | ||
+ | } | ||
+ | |||
+ | public int getValue() { | ||
+ | return value; | ||
+ | } | ||
+ | |||
+ | public Colors getColor() { | ||
+ | return color; | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public String toString() { | ||
+ | return " | ||
+ | " | ||
+ | ", color=" | ||
+ | ' | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Main.java === | ||
+ | |||
+ | Il n'y a qu'à la création de la carte qu'il faut toucher. Le reste fonctionne toujours. | ||
+ | |||
+ | <code java> | ||
+ | // snip | ||
+ | Card setDeCoeur = new Card(7, Colors.HEART); | ||
+ | //snip | ||
+ | </ | ||
+ | |||
+ | ===== v4 : Egalité entre cartes ===== | ||
+ | |||
+ | En java l' | ||
+ | * tester l' | ||
+ | * tester l' | ||
+ | |||
+ | Exemple du code ci-dessous exécuté dans le main : | ||
+ | <code java> | ||
+ | private static void testEqualityCard() { | ||
+ | Card asDePique = new Card(1, Colors.SPADE); | ||
+ | System.out.println(asDePique == asDePique); | ||
+ | System.out.println(asDePique == new Card(1, Colors.SPADE)); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Pour l' | ||
+ | |||
+ | On peut voir ces méthodes comme des méthodes de conversion d' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | <note warning> | ||
+ | On ne génère **jamais** '' | ||
+ | |||
+ | C'est à savoir si vous faites vous-même ces méthodes pour vos objets. | ||
+ | </ | ||
+ | |||
+ | <note tip> | ||
+ | Notions vues : | ||
+ | * les [[[[public: | ||
+ | * égalité entre objets ([[public: | ||
+ | * [[http:// | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Card.java === | ||
+ | |||
+ | On laisse Intellij générer les méthodes. C'est un peu sale mais ça fait le job. Regardez [[http:// | ||
+ | |||
+ | === Main.java === | ||
+ | |||
+ | <code java> | ||
+ | //snip | ||
+ | private static void testEqualityCard() { | ||
+ | Card asDePique = new Card(1, Colors.SPADE); | ||
+ | System.out.println(asDePique == asDePique); | ||
+ | System.out.println(asDePique == new Card(1, Colors.SPADE)); | ||
+ | System.out.println(asDePique.equals(new Card(1, Colors.SPADE))); | ||
+ | System.out.println(new Card(1, Colors.SPADE).equals(asDePique)); | ||
+ | } | ||
+ | // | ||
+ | </ | ||
+ | |||
+ | ==== v5 : Constructeur par défaut ==== | ||
+ | |||
+ | Moins il y a de paramètres à une méthode, mieux c'est. Uncle Bob dans son livre [[http:// | ||
+ | |||
+ | <note tip> | ||
+ | Notions vues : | ||
+ | * [[http:// | ||
+ | * [[public: | ||
+ | </ | ||
+ | |||
+ | === Card.Java === | ||
+ | |||
+ | <code java> | ||
+ | //snip | ||
+ | public Card() { | ||
+ | this(1, Colors.SPADE); | ||
+ | } | ||
+ | //snip | ||
+ | </ | ||
+ | |||
+ | ===== Diagramme UML final ===== | ||
+ | |||
+ | {{: | ||
+ | < | ||
+ | enum Colors { | ||
+ | SPADE | ||
+ | DIAMOND | ||
+ | HEART | ||
+ | CLUB | ||
+ | } | ||
+ | |||
+ | class Card { | ||
+ | -int value | ||
+ | -Colors: color | ||
+ | +Card(int: value, Colors: color) | ||
+ | +Card() | ||
+ | |||
+ | +int getValue() | ||
+ | +Colors getColor() | ||
+ | +String toString() | ||
+ | +boolean equals(Object o) | ||
+ | +int hashcode() | ||
+ | } | ||
+ | |||
+ | Card o-- Colors : color | ||
+ | </ |