IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

Accéder à toutes les instances d'une classe


Sujet :

Delphi

  1. #1
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 17
    Points : 11
    Points
    11
    Par défaut Accéder à toutes les instances d'une classe
    Bonjour !

    Je susi débutant en POO et je fais face à un problème qui ne me parait pas si simple que cela :

    Dans mon simuli-moteur 3d, je charge un certain nombre de mesh et j'aimerai évidemment ne pas avoir à ouvrir/fermer mon fichier à chaque fois. Pour cela j'aimerai faire un test, à savoir comparer les champs de mes instances de ma classe Objet3D afin de savoir si le fichier a déjà été parsé afin de recopier directement les données depuis l'instance déjà existante.

    Le problème c'est que je ne sais pas comment boucler sur toutes les instances de cette classe...

    Merci d'avance !

  2. #2
    Membre chevronné Avatar de philnext
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    1 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 552
    Points : 1 780
    Points
    1 780
    Par défaut
    tes instances c'est quoi en fait ?
    * Si c'est toi qui les gères entièrement le plus simple c'est de les ajouter dans un TList à chaque création, et après ce TList te permet de toutes les retrouver.
    * Si ce sont des instances 'visuelles' déposées sur un composant TWinControl (TForm par exemple) regarde l'aide de ControlCount qui montre comment gérer tous les 'Controls' enfants d'un composant.

  3. #3
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 17
    Points : 11
    Points
    11
    Par défaut
    Bonsoir ^^

    j'appelle instance les objets issus de mes classes. Ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TabObjet[i] := TObjet3D.Create(...)
    avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      TObjet3D = class
     
     
        public
     
             id : GluInt;  //id de la display list
             nbv,nbf : integer;
             mesh_name : string ;
     
             etc, etc, etc
    J'aimerai pouvoir y accéder depuis mon constructeur.

  4. #4
    Membre chevronné Avatar de philnext
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    1 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 552
    Points : 1 780
    Points
    1 780
    Par défaut
    Ben je ne comprends pas trop : tu as la liste de toutes tes instances dans
    TabObjet[i] non ?

  5. #5
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 17
    Points : 11
    Points
    11
    Par défaut
    mmuh mais oui ^^;
    Mais pour y accéder depuis mon constructeur il faudrait alors que je le passe en paramètre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TabObjet[i] := TObjet3D.Create(..., @TabObjet, ... );
    Le problème alors est que je m'embrouille avec le prototype du constructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     constructor Create( ....
                    instances : ???;
                    ....);
    quel est le type de instances ? Pointer ?
    Dans ce cas comment accéder à mes champs ?
    Assurément, ca ne fonctionne pas.
    Ca devient compliqué si je dois créer un type Machin : Array of MyClass
    et qu'ensuite je dois faire un

    J'ai tout de même essayé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    type Machin : Array of TObjet3D
     
    TabObjet : Machin
    PTabObjet : ^Machin
     
     
    TabObjet[i] := TObjet3D.Create(..., PTabObjet, ... );
    mais alors je ne peux pas écrire le constructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     constructor Create( ....
                    instances : PTabObjet;
                    ....);
    puisque PTabObjet est défini comme étant un pointeur sur un tableau contenant cette classe (dépendances cycliques toussa...) !


    Je suis un peu perdu en fin de compte.

  6. #6
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Aaah.. on touche là un choix fait par les développeurs de chez Borland, et que j'ai toujours trouvé extrêmement discutable, même si ce choix facilite l'écriture du code.

    Règle : Dans le compilateur de Delphi, les objets sont automatiquement référencés en tant que pointeurs, mais déréferencés automatiquement dans l'écriture du code utilisant ces objets (champs, priopriétés, appels de méthode).

    Contrairement à ce qui était le cas dans les antiques versions de Turbo Pascal.

    Par exemple :
    Citation Envoyé par MrGecko
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TabObjet[i] := TObjet3D.Create(..., @TabObjet, ... );
    Ici, l'arrobas est non seulement inutile, mais fausse, puisqu'elle va renvoyer un pointeur, non sur l'instance mais sur la variable pointeur contenant l'adresse de cette instance !

    Citation Envoyé par MrGecko
    quel est le type de instances ? Pointer ?
    Dans ce cas comment accéder à mes champs ?
    Eh bien oui, c'est un pointeur, mais le déréférencement automatique des pointeurs d'objets en objets fait que tu ne dois pas le considérer comme un pointeur ! On écrira simplement, sans se préoccuper du contenu de la variable :
    En fait, tout se passe comme si on passait directement l'objet en paramètre valeur, alors qu'en fait, c'est un pointeur qui est transmis pour des raisons d'efficacité.

    Donc, en Delphi, jamais ce genre de code :

    Citation Envoyé par MrGecko
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    type Machin : Array of TObjet3D
     
    TabObjet : Machin
    PTabObjet : ^Machin
     
     
    TabObjet[i] := TObjet3D.Create(..., PTabObjet, ... );
    En Delphi, il n'y a pas besoin de déclarer le pointeur associé du type objet :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    type Machin : Array of TObjet3D
     
    TTabObjet : Machin
     
     
    TabObjet[i] := TObjet3D.Create(..., Objet, ... );
    C'est de toute façon (je me répète) un pointeur qui est transmis.

    Edit : ce qui est extrêmement dommage, c'est que Borland, à ma connaissance, n'a jamais eu idée de proposer une directive de compilation permettant de désactiver ce comportement aifin de pouvoir recompiler rapidement de vieilles unités écrites en TP, TPW, ou BP...

    Edit 2 : Correction d'une erreur de ma part.

  7. #7
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 17
    Points : 11
    Points
    11
    Par défaut
    Bonjour et merci à toi pour ces explications qui bien que m'ayant éclairé et appris quelques choses, ne me satisfont pas encore pleinement, explication ^^ :

    Ici, l'arrobas est non seulement inutile, mais fausse, puisqu'elle va renvoyer un pointeur, non sur l'instance mais sur la variable pointeur contenant l'adresse de cette instance !
    D'après ce que je comprends, je chercher à passer en paramètre un pointeur vers ce tableau d'instance (Arrray of TObjet3D), non pas un pointeur sur une instance.

    Comme tu le dis, c'est un pointeur qui est transmis. Je devrais donc pouvoir écrire mon constructeur comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    constructor TObjet3D.Create( fichier :string;
                                 instances : Pointer ;
                                 x,y,z : GLFloat);
    var
       flux : Text;
       i : integer;
       copy : boolean;
    begin  
     
    writeln('nom de l''instance : ', instances[high(instances)].mesh_name);
    Ce qui me permetterait à chaque appel du constructeur de pouvoir accéder à toutes mes instances déjà crées.

    Eh bien oui, c'est un pointeur, mais le déréférencement automatique des pointeurs d'objets en objets fait que tu ne dois pas le considérer comme un pointeur !
    Le problème vient alors du fait que j'ai déclaré instances comme étant un pointeur :
    En effet je récupère fort logiquement une erreur du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Error: Array type required

    C'est la que je me repose la question de savoir si j'ai bien compris ce que tu as corrigé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TabObjet[i] := TObjet3D.Create(..., Objet:TTabObjet, ... );
    Ca ne m'a pas paru clair, du coup j'ai ré-écris ceci en :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TTabObjet[i] := TObjet3D.Create(..., TTabObjet, ... );
    Peut-être me manque-t-il une directive ou je ne sais quoi qui me permette d'utilise Objet: ?
    De plus TTabObjet est un tableau, ce n'est pas directement un objet, du coup j'avoue ne pas comprendre ce Objet: que tu as rajouté.

    ps: je travaille sous Lazarus avec {$mode Delphi} au début de chacun de mes fichiers.


    Merci encore à vous tous de prendre du temps pour répondre à tout ceci

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    624
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 624
    Points : 754
    Points
    754
    Par défaut
    Tu mélange tout là
    Regardes dans la doc comment déclarer un prototype de fonction.
    Objet -> nom d'un parametre.
    TTabObjet -> type de Objet

  9. #9
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 17
    Points : 11
    Points
    11
    Par défaut
    Désolé, mais je sais déclarer une fonction.
    Que je ne comprenne pas ou soit complétement à côté de la plaque pour cet exemple ne m'étonnerait qu'à moitié.

    Objet -> nom d'un parametre.
    TTabObjet -> type de Objet
    Certes, mais ca ne m'avance pas beaucoup.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TObjet3D.Create(..., Objet:TTabObjet, ... );
    Je ne connais pas cette syntaxe (edit: le fait de mettre Objet: ) et ne l'ai jamais lu nul part.
    J'en suis à peu près exactement au même point qu'hier

    Merci d'avance.

  10. #10
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Citation Envoyé par MrGecko
    Je ne connais pas cette syntaxe (edit: le fait de mettre Objet: ) et ne l'ai jamais lu nul part.
    Gnè ?

    C'est la base même du langage Pascal !

    Tu n'as pas dû lire les bonnes documentations !

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    624
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 624
    Points : 754
    Points
    754
    Par défaut
    Tu mélanges, je pense, appel et prototype de fonction.

    Essayes cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var
      Objet:TTabObjet;
      Truc: TObjet3D;
     ------
     
    truc := TObjet3D.Create(..., Objet, ...);

  12. #12
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Arg ! C'est de ma faute !

    Emporté par mon explication, en voulant insiter sur le fait que le paramètre ne doit pas être de type pointeur, j'avais laissé une déclaration de type dans l'appel du constructeur, ce qui est faux évidemment !

    C'est bien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TabObjet[i] := TObjet3D.Create(..., Objet, ... );
    Où Objet est déclaré du type TTabObjet dans la déclaration de .Create.

    Après, je ne sais pas d'où vient le paramètre objet ni ce que tu veux réellement faire, et je ne suis pas bien sûr que tu aies les idées claires toi-même.

    J'ai corrigé mon premier message. Désolé.

  13. #13
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 17
    Points : 11
    Points
    11
    Par défaut
    edit: ah bah voilà :]

    Je vais re-expliquer simplement ce que j'aimerais faire.

    Mettons j'ai une classe TJoueur avec un membre public nom : string.

    J'aimerai dans le constructeur Create(...) de ma classe TJoueur pouvoir accéder à tous les nom de mes joueurs déjà crées pour pouvoir par exemple détecter si deux joueurs ont le même nom. Ma technique précédente est de toute façon mauvaise, oublions-la.

    Comment feriez-vous ?

    Encore merci de donner de votre temps pour m'aider.

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    624
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 624
    Points : 754
    Points
    754
    Par défaut
    Une solution simple à mettre en oeuvre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        ListBox1: TListBox;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
      {$M+}
      TJoueur = class(TObject)
      private
        FPlayerName: string;
        procedure SetPlayerName(const Value: string);
      public
        class function IsValidName(List: TStrings; NewName: string): boolean;
        constructor Create(NewName: string);
      published
        property PlayerName: string read FPlayerName write SetPlayerName;
      end;
     
    var
      Form1: TForm1;
      List: TStrings;
    implementation
     
    uses
      typinfo;
    {$R *.DFM}
     
    { TJoueur }
     
    constructor TJoueur.Create(NewName: string);
    begin
      FPlayerName := NewName;
    end;
     
    class function TJoueur.IsValidName(List: TStrings; NewName: string): boolean;
    begin
      // tester if assigned(list) then 
      Result := List.IndexOf(NewName) < 0;
      if Result then List.Add(NewName) else
        MessageDlg(Format('%s existe déjà dans un autre objet', [NewName]),
          mtWarning, [mbOk], 0);
    end;
     
    procedure TJoueur.SetPlayerName(const Value: string);
    begin
      FPlayerName := Value;
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      J, K, L: TJoueur;
    begin
      if TJoueur.IsValidName(List, 'TOTO') then
       J := TJoueur.Create('TOTO');
     
      if TJoueur.IsValidName(List, 'RIRI') then
       K := TJoueur.Create('RIRI');
     
      if TJoueur.IsValidName(List, 'RIRI') then
       L := TJoueur.Create('RIRI');
     
      ListBox1.Items.Add(J.PlayerName);
      ListBox1.Items.Add(K.PlayerName);
     
      FreeAndNil(J);
      FreeAndNil(K);
     
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      List := TStringList.Create;
    end;
     
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      // tester if assigned(list) then 
     FreeAndNil(List);
    end;
     
    end.
    Une solution basée sur le modèle TCollection/TCollectionItem est plus propre que le code proposé.

  15. #15
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2006
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2006
    Messages : 17
    Points : 11
    Points
    11
    Par défaut
    Ok merci je comprends à peu près ce que tu fais même si je n'ai encore jamais touché à tout ce qui est boite de dialogue en Delphi.

    En fait tu n'accèdes pas directement aux objets mais tu copies le champs FPlayerName de chaque objet dans une liste à part pour pouvoir les comparer ?
    Je pourrai faire ca mais je suis ammené à accéder à d'assez gros tableaux de nombreuses fois et ca serait un peu bête de devoir tous les recopier.

    J'étais passé par un tableau en global mais je me suis ravisé pour cette raison.

  16. #16
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    624
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 624
    Points : 754
    Points
    754
    Par défaut
    Pour éviter le tableau de portée globale, il y a toujours la possibilité de l'encapsuler dans une classe conteneur qui gére la creation des objets sur le modele TComponent/TComponentList ou avec une TObjectList.

    Sinon en lisant cela
    afin de savoir si le fichier a déjà été parsé
    dans ce cas tu peux utiliser un boolean.

Discussions similaires

  1. WMI : Nom de toutes les instance d'une classe
    Par Chachane dans le forum C++
    Réponses: 1
    Dernier message: 02/07/2010, 15h34
  2. retourner les instances d'une classe
    Par docky dans le forum C++
    Réponses: 2
    Dernier message: 14/05/2008, 20h51
  3. Utilisation de toutes les instances d'une classe dans un while
    Par canaboss dans le forum Débuter avec Java
    Réponses: 12
    Dernier message: 28/04/2008, 15h28
  4. comment trier les instances d'une classe selon un attribut choisi
    Par rddev dans le forum Collection et Stream
    Réponses: 4
    Dernier message: 29/05/2007, 00h01
  5. Connaitre toutes les instances d'une classe
    Par miniseb dans le forum Langage
    Réponses: 14
    Dernier message: 09/01/2006, 17h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo