orienté objet: accéder à un attribut dans un *autre* classe

L’auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

bonjour j’ai besoin de comprendre comment résoudre ce problème en java.

J’ai un projet et j’ai simplifié ici le code volontairement… j’ai un tableau board où s’affiche des données, comme la taille de la map…..

…mais map et board sont deux objets séparés, donc comment board peut-il savoir les dimension de map ?

Tout est mieux expliqué dans le code java:

public class Main {
    public static void main(String[] args) {}
}


public class Window {
    private Map map = new Map();
    private Board board = new Board();
    
    public Window() {}
}


public class Map {
    private final int MAP_SIZE_X = 25;
    private final int MAP_SIZE_Y = 15;
    
    public Map() {}
    
    public int getMapX() {
        return MAP_SIZE_X;
    }
    
    public int getMapY() {
        return MAP_SIZE_Y;
    }
}


public class Board {
    public Board() {}

    public void paint() {
        // J'ai besoin de récupérer ici les dimensions de
        // la map pour les afficher dans le tableau board
        
        int mapX; // mapX doit être égal à MAP_SIZE_X
    }
}

comment résoudre le problème ligne 37 ?… (le code compile si ça peut aider) des pistes?

+0 -0

Cette réponse a aidé l’auteur du sujet

Bonjour,

Une possibilité (s’il n’y a qu’une seule Map dans un Board) est d’utiliser des attributs statiques :

public class Main {
    public static void main(String[] args) {}
}


public class Window {
    private Map map = new Map();
    private Board board = new Board();
    
    public Window() {}
}


public class Map {
    private static final int MAP_SIZE_X = 25;
    private static final int MAP_SIZE_Y = 15;
    
    public Map() {}
    
    public static int getMapX() {
        return MAP_SIZE_X;
    }
    
    public static int getMapY() {
        return MAP_SIZE_Y;
    }
}


public class Board {
    public Board() {}

    public void paint() {
        // J'ai besoin de récupérer ici les dimensions de
        // la map pour les afficher dans le tableau board
        
        int mapX = Map.getMapX();
        int mapY = Map.getMapY();
    }
}

Tes attributs MAP_SIZE_X et MAP_SIZE_Y pourront alors être récupérés sans instancier Map.

Édité par tokpela

+0 -0

Cette réponse a aidé l’auteur du sujet

De manière plus élégante, soit envoyer dans le constructeur de Board les dimensions de map (si seules ces valeurs importent) voire une référence vers Map si jamais Board doit interagir avec.

Les static ne sont pas pertinents ici.

Amateur de Logiciel Libre et de la distribution GNU/Linux Fedora. #JeSuisArius

+1 -0

C’est pas très élégant certes, mais j’ai du mal à comprendre en quoi ce n’est pas pertinent…

[EDIT] J’ai eu ma réponse avec le message ci-dessous :)

Édité par tokpela

+0 -0
Auteur du sujet

alors comme le jeu se fait sur plusieurs villes, il devra y avoir plusieurs maps. le static ne marche donc pas….

De manière plus élégante, soit envoyer dans le constructeur de Board les dimensions de map (si seules ces valeurs importent) voire une référence vers Map si jamais Board doit interagir avec.

Les static ne sont pas pertinents ici.

Renault

ça me fait penser à une autre idée: que penser si je mets une nouvelle Méthode dans la Classe Window qui se charge de "dessiner sur le board" les dimensions de la map? … donc ma fenêtre irait elle même dessiner les dimensions de sa map dans le board, serait-ce possible?

car je ne vois que Window qui contient les infos de map?

+0 -0

Cette réponse a aidé l’auteur du sujet

C’est pas très élégant certes, mais j’ai du mal à comprendre en quoi ce n’est pas pertinent…

Les classes statiques ne doivent pas être utilisées à tort et à travers. En orienté objet tu dois au maximum utiliser des classes normales et réfléchir à la relation entre les classes plutôt que de mettre leurs propriétés dans un pot commun et que n’importe qui tape dedans n’importe comment. Cela rend le code moins flexible et si jamais tu veux multiplier les objets cela ne fonctionne plus.

Le static doit être réservé aux cas spécifiques qui se justifient. Par exemple pour faire un singleton, ou si ta classe n’a pas vraiment d’état interne (cas de la classe Math).

ça me fait penser à une autre idée: que penser si je mets une nouvelle Méthode dans la Classe Window qui se charge de "dessiner sur le board" les dimensions de la map? … donc ma fenêtre irait elle même dessiner les dimensions de sa map dans le board, serait-ce possible?

C’est difficile de t’éclairer sans avoir plus de précisions sur le projet. Notamment sur qui fait quoi exactement, et la relation exacte entre tes classes.

Tu as plusieurs manières de faire :

  • On considère que Board est lié à une carte précise, alors c’est Board qui crée la Map ou qui reçoit une référence vers celle-ci pour pouvoir la manipuler directement ;
  • On considère que Board et Map sont des entités qui n’ont pas de liens réels en dehors de l’affichage, par exemple Board pourrait utiliser ailleurs des coordonnées qui n’ont rien à voir avec ta classe Map, alors ta classe Window peut gérer tes deux classes comme actuellement et fait le lien entre les deux (elle récupère les infos nécessaires de Map pour les injecter dans Board).

Il faut que tu éclaircisses la relation entre tes classes pour dégager la meilleure architecture pour ton code. Cela rendra ton code plus simple et élégant, plus maintenable également. Même si en soit n’importe quelle méthode peut rendre ce que tu veux faire fonctionnel.

Amateur de Logiciel Libre et de la distribution GNU/Linux Fedora. #JeSuisArius

+1 -0
Auteur du sujet

mini question en parallèle: les setters, idéalement, devraient contenir des conditions?

public boolean setMapX(int sizeX) {
    if (sizeX > 0 && sizeX < 50) {
        mapSizeX = sizeX;
        return true;
    }
    return false;
}

sinon je vois vraiment pas pourquoi on s’embête avec des getters et setters…

Renault là je dois y aller mais je répond après… a tout à l’heure!

+0 -0

Cette réponse a aidé l’auteur du sujet

Il n’est pas obligatoire qu’un setter ou un getter ait des conditions. Cela dépend de ce que tu fais. Les conditions sont nécessaires pour éviter par exemple des valeurs invalides pour une propriété donnée qui pourrait casser le bon fonctionnement de ta classe. Par exemple si tu envoie un nombre négatif pour la taille de quelque chose, cela pourrait mettre en défaut tes autres fonctions internes qui supposent que la valeur est positive.

Mais ce n’est pas parce que de telles conditions n’existent pas encore que ces fonctions ne servent à rien. L’avantage des getter / setter c’est que l’interface externe ne bouge pas (normalement) mais le comportement interne peut évoluer. Sans les getter / setter, le moindre changement de la représentation interne t’obligera à adapter les classes qui utilisent ces propriétés directement. Avec le getter / setter, tu peux garantir une interface publique pour les autres classes tout en changeant comment cela fonctionne en interne. Ainsi si tu changes cela, les classes qui se servent de ces propriétés n’ont pas à subir des changements ou de manière mineure.

Amateur de Logiciel Libre et de la distribution GNU/Linux Fedora. #JeSuisArius

+0 -0
Auteur du sujet

Il faut que tu éclaircisses la relation entre tes classes pour dégager la meilleure architecture pour ton code. Cela rendra ton code plus simple et élégant, plus maintenable également. Même si en soit n’importe quelle méthode peut rendre ce que tu veux faire fonctionnel.

Alors en fait dans mon projet il n’y a qu’un et un seul Board (=menu de droite) qui affiche les détails de la map se trouvant à gauche (une map = une ville).

du coup je me dis que pour être OK sur l’architecture je prend la deuxième solution que tu proposes, que Window gère l’affichage sur le Board en lui donnant la Map dont on veut les détails….

ça me parait logique qu’en pense tu?

merci pour l’autre réponse par ailleurs! PS : j’ai mis mapSizeX en attribut Non Static et privé.

Édité par marius007

+0 -0

Cette réponse a aidé l’auteur du sujet

Hello,

Petit conseil en plus, le sujet étant déjà traité : n’utilise pas une classe nommée, Map, c’est une interface très utilisée en Java et le langage ne supporte pas les alias, donc si à un moment t’as besoin d’utiliser java.util.Map ça va te faire des noms à rallonge partout.

mini question en parallèle: les setters, idéalement, devraient contenir des conditions?

public boolean setMapX(int sizeX) {
    if (sizeX > 0 && sizeX < 50) {
        mapSizeX = sizeX;
        return true;
    }
    return false;
}

marius007

Oui, mais dans ce cas il vaut mieux lancer une exception (eg. IllegalArgumentException ou mieux ta propre exception pour ce cas) plutôt que renvoyer un booléen.

+0 -0
Auteur du sujet

D’accord merci et je ne mets plus en résolu car j’ai un nouveau problème jamais vu et très subtile il me semble…..

sachant que toutes les autres classes de mon code ne contient aucune erreur aucun avertissement….

aaaaaah
aaaaaah

Le System.out.prinln ne fonctionne plus. ????

Et recherche Google n’a pas aidé…

+0 -0
Auteur du sujet

Petit conseil en plus, le sujet étant déjà traité : n’utilise pas une classe nommée, Map, c’est une interface très utilisée en Java et le langage ne supporte pas les alias, donc si à un moment t’as besoin d’utiliser java.util.Map ça va te faire des noms à rallonge partout.

Chinoisfurax

Je vais suivre ton conseil car je me demande par quoi remplacer Map dans mon projet? En anglais, un synonymes de Map c’est Card mais ça fait trop carte de banque… des idées ?

après je passe le sujet en résolu.

Édité par marius007

+0 -0

Cette réponse a aidé l’auteur du sujet

bonjour j’ai besoin de comprendre comment résoudre ce problème en java.

public class Board {
public void paint() {
    // J'ai besoin de récupérer ici les dimensions de
    // la map pour les afficher dans le tableau board
comment résoudre le problème ligne 37 ?... (le code compile si ça peut aider)

Le problème se résoud en définissant mieux les responsabilités de chaque classe.

Admettons que

  • la classe Map contienne le "tableau des pieces",
  • et que Board soit chargé de dessiner.

Chacun son boulot, hein. Faut juste savoir qui demande à dessiner la map sur le board.

Alors il pourrait y avoir, dans Board, une méthode void draw(Map map) à qui on (on = une instance de Window ?) demande de dessiner la map indiquée.

Ou dans Map, une méthode void drawOn(Board board).

Édité par MichelBillaud

+0 -0
Auteur du sujet

Chacun son boulot, hein. Faut juste savoir qui demande à dessiner la map sur le board.

Quel est la meilleure option en termes de bonne pratique?

… parce qu’alors j’avais carrément une autre idée et je pense qu’elle est bien.

On a un objet Map qui représente la carte du jeu sur laquelle se déplace le personnage. A droite on a un tableau Board qui affiche les données utiles du jeu (PV du personnage, dimensions de la Map…

donc Map pourrait être…. un attribut (privé) de Board ! Car comme ça Board peut à tout moment accèder aux données de Map:

public class Board {
    private Map map;

    public Board(Map map) {
        this.map = map;
    }
}

et map est donné par le constructeur qui prend map créé par le jeu...

Est ce une bonne idée?

+0 -0

Cette réponse a aidé l’auteur du sujet

Ca peut se faire comme ça.

Ce que ça dit, c’est qu’une Board est liée, à sa construction, à une Map créee auparavant.

Tu peux même ajouter l’attribut final, parce qu’une Board ne change pas de Map pendant son existence.

+0 -0
Auteur du sujet

Nickel et alors tant que tu en parles, j’aimerais justement savoir quand utiliser le mot clef final.

Ma règle actuelle c’est « utilise toujours final dès que tu peux » donc:

  1. final sur une classe qui ne possède pas de classe fille
  2. final sur une CONSTANTE

Est-ce une bonne pratique, est-ce une bonne façon d’utiliser final ?

+0 -0

Cette réponse a aidé l’auteur du sujet

Existe aussi sur les méthodes, dont on ne veut pas qu’elles soient surchargées par des classes filles.

Il faut s’entendre sur ce que veut dire "constante". Pour un type de base, y a pas de souci, mais pour une référence, ça veut que la référence vers un objet ne peut plus être changée au dela du constructeur. Exemple

class A {
   private final ArrayList<Integer> entiers;
   
   public A () {
       entiers = new ArrayList();
   }

   public void ajouter(int n) {
       entiers.add(n);
   }
}

Dans les autres méthodes, on ne peut pas affecter quelque chose à entiers, mais par contre on peut agir dessus pour modifier son état.

Principe : le mettre pour les attributs dont on sait qu’ils ne changeront pas. Pour les classes et méthodes, à faire impérativement pour les choses qui ne doivent pas être surchargées/redéfinies.

Comme ça le compilateur signale des erreurs très bêtes et très chiantes à retrouver, et on peut rêver que ça permette aussi de générer du code plus efficace.

Édité par MichelBillaud

+0 -0

Cette réponse a aidé l’auteur du sujet

Oui, pour les raisons indiquées plus haut. Sauf si bien sûr on ne commet jamais d’erreurs en programmant, c’est à dire qu’en réalité on ne programme jamais.

Édité par MichelBillaud

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte