Passer en paramètre un tableau d'objet à  2 dimension (objective-c)

clandestinoclandestino Membre
00:35 modifié dans API AppKit #1
Salut!
Je suis tout nouveau dans la programmation en obj-c et la j'ai un petit problème de passage de paramètre.
J'ai chercher la solution mais... je suis pas tombé dessus...
Voici mon problème:
<br />@interface Party : NSObject {<br />&nbsp;  Piece* board [8][8];<br />}<br />-(void)startNew:(Piece*) board[8][8];<br />@end<br />

J'ai l'attribut board qui est un tableau d'objet pièce à  2 dimentions. (cela fonctionne)
J'aimerais passer cet objet comme paramètre à  la méthode startNew mais au niveau de la syntaxe ca coince un peu, j'ai essayé tout se que je connais (en c):
-(void)startNew:(Piece***) board;
-(void)startNew:(Piece*[][]) board;
...
ca passe pas.
Si qq'un à  la solution, c'est avec plaisir!
Merci

Réponses

  • schlumschlum Membre
    00:35 modifié #2
    -(void)startNew:(Piece*[8][8]) board;
    

    ;)

    ou alors :
    -(void)startNew:(Piece*&#91;][8]) board;
    



    (mais tu ne peux pas avoir deux indices "vides", comme en C !)
  • clandestinoclandestino Membre
    00:35 modifié #3
    C'est le seul truc que j'avais pas encore essayé  :o
    Merci!!
  • clandestinoclandestino Membre
    00:35 modifié #4
    Ouai mais y a tjs problème à  l'implémentation:
    <br />-(void)startNew:(Piece*[8][8]) board{<br />&nbsp;  self-&gt;board = board;<br />}<br />
    

    Erreur: Type incompatible... ???? Je comprends pas ou est la différence.
  • 00:35 modifié #5
    Juste mon petit grain de sel: passer un tableau d'objet en argument est tout à  fait correct en terme de code, mais en terme de logique "objet" ce n'est pas recommandé: il vaut mieux que tu fasses un objet "Board" avec des accesseurs pour accéder aux pièces, et que tu passes un objet Board en argument.
  • clandestinoclandestino Membre
    00:35 modifié #6
    Ouai tu as raison, mais dans mon cas ca me facilite grandement la vie d'utiliser un tableau à  2 dimension qu'un objet qui contiendrait tous mes éléments.
    Tu as la solution à  mon problème?
  • schlumschlum Membre
    00:35 modifié #7
    dans 1173439619:

    Ouai mais y a tjs problème à  l'implémentation:
    <br />-(void)startNew:(Piece*[8][8]) board{<br />   self-&gt;board = board;<br />}<br />
    

    Erreur: Type incompatible... ???? Je comprends pas ou est la différence.


    Le passage d'un tableau est toujours fait par pointeur...
    Alors que ta variable de classe est allouée en statique !

    Il va falloir que tu fasses un "memcpy".

    -(void)startNew:(Piece* [8][8])b<br />{<br />    memcpy(self-&gt;board,b,sizeof(board));<br />}
    
  • 00:35 modifié #8
    dans 1173440834:

    Ouai tu as raison, mais dans mon cas ca me facilite grandement la vie d'utiliser un tableau à  2 dimension qu'un objet qui contiendrait tous mes éléments.


    Pas sur que ça te facilite la vie, enfin plus exactement pas sûr que ça te la facilitera: tu rends ton code tributaire d'une structure de données bien précise et c'est contraire à  la logique objet. Bête exemple, supposons que par la suite tu te rendes compte que ton tableau C n'est pas la meilleure représentation, et qu'il vaut mieux stocker la position d'une pièce dans la classe "Piece" plutôt que dans le "Board" et utiliser un ensemble (ensemble = collection à  0 dimensions) pour stocker les pièces présentes sur le tableau. Dans ton cas, tu vas devoir aller chercher partout le code qui fait référence à  ce tableau, alors que si tu as une classe Board qui a une méthode pieceAtX:(unsigned)x y:(unsigned)y, tu modifies juste cette méthode pour aller chercher la pièce dans la collection de pièces qui est sur le plateau, et tout le code que tu as écrit avant restera opérationnel.

    Sans compter qu'il y a pas mal de trucs que tu pourrais centraliser dans une classe "Board"...

    Comme tu dis être débutant en objective-c, il vaut mieux prendre directement les bonnes habitudes, même si ça te semble contraire à  ce que tu penses être le mieux, non?
  • clandestinoclandestino Membre
    00:35 modifié #9
    HA ouai... mes notions de C revienne  :fouf):
    En fait il faut que je fasse un truc comme ca:
    <br />@interface Party : NSObject {<br />&nbsp;  Piece*** board;<br />}<br />-(void)startNew:(Piece***) board;<br />@end<br /><br />@implementation Party<br />-(void)startNew:(Piece***) board{<br />&nbsp;  self-&gt;board = board;<br />}<br />@end<br />
    

    Merci pour votre aide!
  • schlumschlum Membre
    00:35 modifié #10
    dans 1173443830:

    HA ouai... mes notions de C revienne  :fouf):
    En fait il faut que je fasse un truc comme ca:
    <br />@interface Party : NSObject {<br />&nbsp; &nbsp;Piece*** board;<br />}<br />-(void)startNew:(Piece***) board;<br />@end<br /><br />@implementation Party<br />-(void)startNew:(Piece***) board{<br />&nbsp; &nbsp;self-&gt;board = board;<br />}<br />@end<br />
    

    Merci pour votre aide!


    Euh ouais, enfin là  c'est très laid... Tu passes le pointeur directement à  la classe. Et qui s'occupe de la gestion mémoire de ce pointeur ?  :o (surtout s'il est défini en statique quelque-part avec une durée de vie limitée, tu fonces dans le mur).
  • clandestinoclandestino Membre
    00:35 modifié #11
    Ouai, j'avais oublié ca aussi...
    Bon je vais allé me gratter la tête un moment et revoir tout ca lol
  • AliGatorAliGator Membre, Modérateur
    00:35 modifié #12
    Hello et bienvenue.

    Je suis assez d'accord avec Renaud, avoir des notions de C c'est très utile pour se mettre à  l'Obj-C, et de toute façon l'Obj-C est une "surcouche" du C, mais il n'empêche que le but c'est de faire de la programmation orientée objet, donc autant prendre les bonnes habitudes et t'y mettre dès le début, non ?

    Au moins pour commencer à  rentrer dans l'idée, et si tu n'es pas encore prêt à  faire un objet Board comme te le conseille Renaud, passe au moins par un tableau au sens objet, plutôt que de continuer à  utiliser les tableaux C.

    Pour cela il y a la classe NSArray en Cocoa : elle te permet de gérer des tableaux d'objets quelconques : cela peut être des pièces, mais aussi un autre tableau.
    Donc dans l'idée déjà  si tu commences par là  (pour te détacher petit à  petit de l'aspect tableau/pointeur pur C), je te conseille de mettre [tt]board[/tt] comme étant un NSMutableArray (sous-classe de NSArray pour les tableaux modifiables, et tu sais en interne que ce sera un NSMutableArray... de NSMutableArray d'objets Piece (un tableau de tableau de pièces, quoi)
    @interface Party : NSObject {<br />&nbsp; NSMutableArray* board;<br /><br />&nbsp; /* en Cocoa on ne manipule que des pointeurs, à  la limite 95% des programmeurs Cocoa<br />&nbsp; ne voient pas &quot;NSArray*&quot; comme un pointeur vers un objet NSArray, mais juste<br />&nbsp; comme un tableau (un NSArray), vu qu&#39;on met un &quot;*&quot; derrière les NSObjects à  toutes<br />&nbsp; les sauces, c&#39;est presque vu comme partie intégrante du nom de la classe.<br />&nbsp; (D&#39;ailleurs si tu ne mets pas le &quot;*&quot; derrière NSArray le compilo va gueuler)<br />&nbsp; */<br />}<br />- (Piece*)pieceAtX:(int)x andY:(int)y;
    
    Et si on suppose que ton tableau en interne est organisé par ligne d'abord, par colonne ensuite, ça donne :
    - (Piece*)pieceAtX:(int)x andY:(int)y<br />{<br />&nbsp; // on récupère le tableau de Pièces correspondant à  la ligne y<br />&nbsp; NSMutableArray* ligne = [board objectAtIndex:y];<br />&nbsp; // puis la pièce à  la position x dans cette ligne<br />&nbsp; Piece* piece = [ligne objectAtIndex:x];<br /><br />&nbsp; // et voilà  !<br />&nbsp; return piece;<br />}
    
    Si tu as compris le principe pour cet exemple, tu es sur la bonne voie pour la POO :) (et en plus, allez, je t'avoue : en fait finalement en faisant ça tu es presque déjà  à  la classe Board dont parlait Renaud en fait :D)

    Allez, la petite remarque de fin pour paufiner : en anglais, "Party" veux dire "fête", "fiesta" (au sens de "Surprise-Party" si tu veux), pas "partie" au sens jeu. Une partie (de jeu) se dit "Game" ;)
    (C'était la petite touche de détail pour terminer :D)
  • schlumschlum Membre
    mars 2007 modifié #13
    et "Piece" veut dire "morceau"  ;D (-> "room")

    Par contre, je ne suis pas d'accord pour dire qu'il faut occulter le pointeur. C'est essentiel de savoir que c'est un pointeur et que (contrairement au C++) quand on fait "id obj1 = obj2", on utilise pas un constructeur de recopie, mais on a juste deux objets identiques (si on modifie un, l'autre sera modifié aussi).
    Mais c'est vrai qu'on ne peut pas faire d'instance "statique".
  • AliGatorAliGator Membre, Modérateur
    00:35 modifié #14
    dans 1173448918:
    Par contre, je ne suis pas d'accord pour dire qu'il faut occulter le pointeur.
    Ouais, en fait si j'ai fait un petit blabla sur cet aspect là  c'est plus pour expliquer à  clandestino qu'il ne fallait pas le voir au sens "tableau" (là  où il utilisait un Piece*** pour un pointeur de tableau de tableau).

    Donc oui NSMutableArray* est un pointeur mais je le met en pointeur non pas pour l'aspect tableau, mais parce que tous les objets Cocoa (NSObjects) sont gérés avec des pointeurs et pas des instances statiques. J'aurais mis NSString* c'était pareil, le pointeur n'a rien à  voir avec le fait qu'on utilise des tableau dans mon exemple.

    Voilà  c'était juste lever le risque de confusion à  ce niveau :D
  • schlumschlum Membre
    00:35 modifié #15
    Le truc aussi, c'est que simuler un tableau à  deux indices avec un NSArray, c'est pas forcément évident...
    Je serais curieux de savoir pourquoi stocker 8*8 pointeurs vers une autre classe  ???
  • AliGatorAliGator Membre, Modérateur
    mars 2007 modifié #16
    dans 1173452720:
    Le truc aussi, c'est que simuler un tableau à  deux indices avec un NSArray, c'est pas forcément évident...
    En même temps en C c'est pareil quand on y pense : c'est un tableau de tableaux, tout comme là  on a des NSArray de NSArray ;)

    Mais justement après tu peux stocker ça comme tu veux en interne (c'est ce qu'a expliqué Renaud) : à  partir du moment où tu as des méthodes comme [tt](Piece*)pieceAtX:(unsigned int)x Y:(unsigned int)y[/tt] et [tt]setPiece:(Piece*)piece atX:(unsigned int)x Y:(unsigned int)y[/tt], tu peux modifier et récupérer les valeurs de ton tableau case par case à  ta guise, sans te soucier de savoir comment c'est géré en interne.

    Après que tu gères ça en un NSArray de NSArray de Pieces, ou un seul NSArray de 64 Pieces, ou encore autrement, il suffit d'adapter l'implémentation des méthodes [tt]pieceAtX:Y:[/tt] et [tt]setPiece:atX:Y:[/tt], mais lorsque tu utilises ça ça ne change rien, puisque grace à  ces 2 méthodes tu peux tout faire sur ton tableau sans te soucier de savoir comment il est géré ;)
  • schlumschlum Membre
    00:35 modifié #17
    D'un autre côté, je doute que NSBitmapImageRep stocke ses pixels sous forme de NSArray de NSArray  :P
    Faut pas cracher sur les styles C aussi, ils font partie intégrante de l'Objective-C  ;)
  • AliGatorAliGator Membre, Modérateur
    00:35 modifié #18
    dans 1173458601:

    D'un autre côté, je doute que NSBitmapImageRep stocke ses pixels sous forme de NSArray de NSArray  :P
    Faut pas cracher sur les styles C aussi, ils font partie intégrante de l'Objective-C  ;)
    Bien sûr, mais à  partir du moment où tu parles de tableaux, c'est quand même plus facile à  manipuler en objet ;)
    Enfin pour moi les types C du genre pointeur de pointeurs de pointeurs c'est plutôt à  éviter (et à  remplacer par des objets plus proprement conçus), et si tu veux utiliser des types C genre un tableau 2D [][], préférer les garder en interne (ou les garder pour le code "pur C" qu'on pourrait mettre dans le .m si jamais tu en as (c'est rare car en général on code tout en Obj-C, mais genre pour les algorithmes ou les codes qui ont besoin d'une rapidité critique ça peut être utile) et mettre une interface Obj-C pour accéder aux éléments ou les modifier (genre pieceAtX:Y: et setPiece:atX:Y:)

    Comme ça ce n'est plus ton type C triple-pointeur que tu passes en paramètre, mais juste un objet, genre Board ou Game.
  • schlumschlum Membre
    00:35 modifié #19
    dans 1173459481:

    dans 1173458601:

    D'un autre côté, je doute que NSBitmapImageRep stocke ses pixels sous forme de NSArray de NSArray  :P
    Faut pas cracher sur les styles C aussi, ils font partie intégrante de l'Objective-C  ;)
    Bien sûr, mais à  partir du moment où tu parles de tableaux, c'est quand même plus facile à  manipuler en objet ;)
    Enfin pour moi les types C du genre pointeur de pointeurs de pointeurs c'est plutôt à  éviter (et à  remplacer par des objets plus proprement conçus), et si tu veux utiliser des types C genre un tableau 2D [][], préférer les garder en interne (ou les garder pour le code "pur C" qu'on pourrait mettre dans le .m si jamais tu en as (c'est rare car en général on code tout en Obj-C, mais genre pour les algorithmes ou les codes qui ont besoin d'une rapidité critique ça peut être utile) et mettre une interface Obj-C pour accéder aux éléments ou les modifier (genre pieceAtX:Y: et setPiece:atX:Y:)

    Comme ça ce n'est plus ton type C triple-pointeur que tu passes en paramètre, mais juste un objet, genre Board ou Game.

    Yep, c'est comme ça que je vois les choses... (juste le NSArray de NSArray qui me chiffonnait  :P j'ose pas imaginer le coefficient qu'on se prend dans la gueule sur le temps d'accès  :) )
  • clandestinoclandestino Membre
    00:35 modifié #20
    Hello et bienvenue.

    Merci, ca fait plaisir de voir qu'il y a une communoté sympatique et dynamique de développeur sur mac  ;)

    Pour la petite histoire, je fais du dev en java depuis quelques années ce qui fait que j'ai quelques notions de POO. Ensuite j'ai fait un peu de C et un tout petit peu de C++.
    Maintenant, cela fait quelque temps que j'ai envie de me mettre l'obj-c et cocoa. J'ai donc lu objective-c précis et concis et pas mal de tuto sur projectomega.
    Je suis vite arrivé à  la conclusion que l'approche d'obj-c et surtout de cocoa est très différente de se que j'ai pu apprendre avec Java.
    Mais le meilleure truc pour rentrer pleinement dans un language c'est de développer qqc et la je suis tombé sur l'article du jeu d'échec. J'ai lu le 2ème et je me suis dis que je n'avais cas développer ma version du jeu et y intégrer un maximum de chose comme la gestion du réseau... et surtout le faire un peu différament parce que les struct (comme utilisé dans la version 2) c'est bien mais quand on a un langage object je pense qu'il y a moyen de faire un peu mieux...

    Le board est en fait le plateau du jeu et je l'utilise dans ma classe qui affiche les pieces et la classe qui gère le jeux (Game anciennement party (et oui c vendredi pas facile des fois ;)))

    J'avais vu que les tableaux était géré par NSArray que j'assimile à  la classe Vector en java (peut-être à  tord...). Ensuite la notion de tableau var[taille] j'aime beaucoup parce que pour moi un tableau c'est une liste de variable fini donc j'ai besoin rapidement et surtout avec une utilisabilité aisé: nom [indice]. C'est pour cette raison que je m'étais tournée vers un tableau à  2 dimension que je crée dans la classe qui affiche et que je transfert à  la classe game avec ce triple pointeur parce que j'ai besoin d'une variable dans Game qui lui fait référence.

    C'est vrai que j'aurais pu faire du NSArray de NSArray mais... je sais pas j'ai de la peine avec cette facon de faire. Peut-etre que j'ai encore de mauvais réflexe qui me vienne du Java??
    Je suis la pour apprendre donc si vous trouvé que je dis n'importe quoi faut pas hésité ! ;)

    PS: Cela dit, pour mon applic je vais devoir revoir mes classes et les réorganisé différament. J'ai fais un peu n'importe quoi pour l'instant, je voulais surtout tester les fonctionnalité de cocoa.
  • 00:35 modifié #21
    dans 1173460218:

    C'est vrai que j'aurais pu faire du NSArray de NSArray mais... je sais pas j'ai de la peine avec cette facon de faire. Peut-etre que j'ai encore de mauvais réflexe qui me vienne du Java??
    Je suis la pour apprendre donc si vous trouvé que je dis n'importe quoi faut pas hésité ! ;)


    En Java aussi tu aurais eu intérêt à  encapsuler les données de ton plateau et utiliser une fonction pour y accéder. L'encapsulation est un principe de base en POO, quel que soit le langage.
  • clandestinoclandestino Membre
    00:35 modifié #22
    n Java aussi tu aurais eu intérêt à  encapsuler les données de ton plateau et utiliser une fonction pour y accéder. L'encapsulation est un principe de base en POO, quel que soit le langage.

    Ouai  ???
    Suivant ce que tu as besoin de faire je préfère utiliser le bon vieux tableau (et c'est meme conseillé) plutot que de sortir l'artierie lourde... En tout cas c'est ce que j'ai appris. Ca c'est pour Java.
    Maintenant pour Obj-c c'est peut-etre autrement. Je connais peux NSArray (voire pas du tout).
  • mars 2007 modifié #23
    Ce n'est pas ce que j'ai dit.

    Ce que j'ai dit, c'est que tu dois encapsuler. Autrement dit avoir une classe Board, et que cette classe doit comporter (au moins) les méthodes:
    [tt]-(Piece*)pieceAtX:(unsigned)x Y:(unsigned)y;
    -(void)setPiece:(Piece*)piece atX:(unsigned)x Y:(unsigned)y;[/tt]

    Et que si tu veux savoir à  quelle pièce faire référence en dehors de la classe Board, tu dois le faire en faisant [myBoard pieceAtX:4 Y:3]; et non pas en allant pointer dans un tableau de pointeurs. Mais à  l'intérieur de la classe Board tu peux utiliser un tableau de pointeurs, si c'est la structure que tu juges (pour le moment) la plus adéquate. Je mets "pour le moment" entre parenthèse non pas parce que c'est une mauvaise idée, mais parce qu'au cours de l'avancement de ton logiciel, tu peux te rendre compte que ce n'est pas le mieux et donc vouloir changer de structure, ce que la logique objet permet très facilement. Donc l'implémentation de pieceAtX:Y: peut très bien être:
    [tt]-(Piece*)pieceAtX:(unsigned)x Y:(unsigned)y {
    return _pieces[ x ][ y ];
    }[/tt]
    ça, ça ne cause aucun problème avec la conception objet.


    Mais ça pourrait être aussi (NSArray de NSArray) :
    [tt]-(Piece*)pieceAtX:(unsigned)x Y:(unsigned)y {
    return [[_pieces objectAtIndex:x] objectAtIndex:y];
    }[/tt]
    Tout comme ça pourrait être (tableau C à  64 éléments):
    [tt]-(Piece*)pieceAtX:(unsigned)x Y:(unsigned)y {
    return _pieces[ x * 8 + y ];
    }[/tt]
    Tout comme ça pourrait être (NSArray contenant les pièces présentes sur le plateau - donc nombre d'éléments variables, la position de la pièce étant stockée dans la classe Piece):
    [tt]-(Piece*)pieceAtX:(unsigned)x Y:(unsigned)y {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@x == %i AND y == %i,x,y];
    return [[_pieces filteredArrayUsingPredicate:predicate] lastObject];
    }[/tt]

    En fait on s'en fout, car pour utiliser la classe Board, tout ce qu'il faut connaitre, c'est [tt]pieceAtX:Y:[/tt], pas comment c'est fait à  l'intérieur.

    Mais ce que je te dis là  n'est pas seulement vrai pour l'obj-c, c'est pareil pour TOUS les langages orienté objet (à  la syntaxe près, évidemment).

    Note: Piece est correct pour le jeu d'échec.
  • clandestinoclandestino Membre
    00:35 modifié #24
    Ha ok,
    Ouai vu sous cet angle je suis tout a fais d'accord avec toi! J'était justement entrain de revoir mes classes et de définir une qui gère le board.
    Merci pour vos conseils!
Connectez-vous ou Inscrivez-vous pour répondre.