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 :

Problème de référence de classe


Sujet :

Delphi

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2002
    Messages : 109
    Points : 71
    Points
    71
    Par défaut Problème de référence de classe
    Bonjour,

    J'ai une classe de base TDocument dans laquelle j'ai créé un constructor virtual et abstract afin que mes sous-classes implémentent obligatoirement ce constructeur.

    De cette façon, je voulais lister mes types de classes dans un TListBox et utiliser le même code du bouton pour créer divers types d'objets dérivés de TDocument.

    J'ai testé le code de cette page et ça fonctionne bien:
    http://laurent-dardenne.developpez.c...es/metaclasse/

    Par contre, je peux seulement l'utiliser pour une classe!

    Dans l'exemple, il y a ceci: TRefMesClasses = class of TMesClasses;

    Dans mon code, j'ai fait TDocuments = class of (TDoc1);

    Sur mon code de bouton, ceci fonctionne et ça appelle le constructeur de la classe TDoc1 (docs étant un TObjectList):

    docs.add(getClassByName(Listbox2.Items.Strings[ListBox2.ItemIndex]).Create());

    Évidemment, le même code sur mon TDoc2 ne fonctionne pas, car je ne suis pas capable de faire un registerClassByName car c'est incompatible avec mon type TDocuments.

    Merci de votre aide!

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2002
    Messages : 109
    Points : 71
    Points
    71
    Par défaut
    En fait, j'essaie de faire exactement comme dans cet exemple:

    http://www.developpez.net/forums/sho...ht=classbyname

    Malheureusement, en créant le type avec ma classe de base, j'obtiens Abstract error de la part du compilateur.

  3. #3
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 434
    Points : 5 846
    Points
    5 846
    Par défaut
    salut

    en fait il faut que tu creer une class abstraite
    genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    TMetaclass = class of  TBaseDocument;
    TBaseDocument = Class(Tobject);
    ...
    end; 
    TDocument = Class(TBaseDocument)
    ...
    end;
    TDoc1 = Class(TBaseDocument)
    ...
    end;
    @+ Phil

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2002
    Messages : 109
    Points : 71
    Points
    71
    Par défaut
    Ça ne fonctionne toujours pas!

  5. #5
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 434
    Points : 5 846
    Points
    5 846
    Par défaut
    salut


    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
    type
      TMetaclass = class of TBasDocument;
     
    var
      ListofObj : TStringList;
     
    // Enregistrer une classe
    procedure registerClassByName(classe: TMetaclass);
    begin
      // Ajout de la classe si elle n'est pas déjà référencée
      if (ListofObj.IndexOf(classe.ClassName) = -1) then
      begin
        ListofObj.AddObject(classe.ClassName,TObject(classe));
      end;
    end;
     
    // Obtenir une classe par son nom
    function getClassByName(nom: string): TMetaclass;
    var
      i : integer;
    begin
      // Recherche dans la liste des classByName
      i := ListofObj.IndexOf(nom);
      // si pas trouvé, on renvoie nil
      if (i = -1) then
      begin
        result := nil;
      end
      // si trouvé, on renvoie la classe associée
      else
      begin
        result := TMetaclass(ListofObj.objects[i]);
      end
    end;
     
    // Au début de l'application, enregistrer les documents :
    ListofObj := TStringList.Create;
    registerClassByName(doc2);
    ...
     
    // Utilisation :
    getClassByName(FormBddSql.DBLookupComboBoxTesteur.Text).Create ...;
    ...
    // Fin d'application, libérer ListofObj
    ListofObj.Free;

    @+ Phil

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2002
    Messages : 109
    Points : 71
    Points
    71
    Par défaut
    Alors là, j'ai créé un nouveau projet de tests avec une classe de base TVehicule et une sous-classe TVoiture. En faisant exactement ce que tu as écris, j'obtiens le même résultat: Abstract error!

    Par contre si je remplace TMetaClass = class of TVehicule par TMetaClass = class of TVoiture, et bien le message « Voiture créée! » s'affiche lorsque je clique sur le bouton.

    Qu'est-ce que je fais de pas correct?

    Merci!

    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
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, contnrs;
     
    type
     
      TMetaClass = class of TVehicule;
     
      TVehicule = class(TObject)
     
         constructor create(); virtual; abstract;
     
      end;
     
      TVoiture = class(TVehicule)
     
         constructor create(); reintroduce;
     
      end;
     
      TForm1 = class(TForm)
        Button2: TButton;
        ListBox1: TListBox;
        procedure FormCreate(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure Button2Click(Sender: TObject);
      private
        { Déclarations privées }
        Vehicules: TObjectList;
        ListofObj: TStringList;
        procedure registerClassByName(classe: TMetaclass);
        function getClassByName(nom: string): TMetaclass;
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.DFM}
     
    // Enregistrer une classe
    procedure TForm1.registerClassByName(classe: TMetaclass);
    begin
      // Ajout de la classe si elle n'est pas déjà référencée
      if (ListofObj.IndexOf(classe.ClassName) = -1) then
      begin
        ListofObj.AddObject(classe.ClassName,TObject(classe));
      end;
    end;
     
    // Obtenir une classe par son nom
    function TForm1.getClassByName(nom: string): TMetaclass;
    var
      i : integer;
    begin
      // Recherche dans la liste des classByName
      i := ListofObj.IndexOf(nom);
      // si pas trouvé, on renvoie nil
      if (i = -1) then
      begin
        result := nil;
      end
      // si trouvé, on renvoie la classe associée
      else
      begin
        result := TMetaclass(ListofObj.objects[i]);
      end
    end;
     
    constructor TVoiture.create();
     
    begin
     
       ShowMessage('Voiture créée!');
     
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
     
       Vehicules := TObjectList.Create();
       ListofObj := TStringList.Create;
     
       registerClassByName(TVoiture);
     
    end;
     
    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
     
       FreeAndNil(Vehicules);
     
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
     
    begin
     
       Vehicules.add(getClassByName(ListBox1.Items.Strings[ListBox1.ItemIndex]).Create());
     
    end;
     
    end.

  7. #7
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 434
    Points : 5 846
    Points
    5 846
    Par défaut
    salut

    2 probleme Trouvé
    Dans ton listbox tu n'as pas mis le nom de tes objet
    et le create de ton decendant n'ete pas override

    Voila le code corrigé

    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
    97
    98
    99
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, contnrs;
     
    type
     
      TMetaClass = class of TVehicule;
     
      TVehicule = class(TComponent)
         constructor create(); virtual; abstract;
      end;
     
      TVoiture = class(TVehicule)
        constructor create(); reintroduce;Override;
      end;
     
      TForm1 = class(TForm)
        Button1: TButton;
        ListBox1: TListBox;
     //   ListBox1: TListBox;
        procedure FormCreate(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure Button1Click(Sender: TObject);
      private
        { Déclarations privées }
        Vehicules: TObjectList;
        ListofObj: TStringList;
        procedure registerClassByName(classe: TMetaclass);
        function getClassByName(nom: string): TMetaclass;
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.DFM}
     
    // Enregistrer une classe
    procedure TForm1.registerClassByName(classe: TMetaclass);
    begin
      // Ajout de la classe si elle n'est pas déjà référencée
      if (ListofObj.IndexOf(classe.ClassName) = -1) then
      begin
        ListofObj.AddObject(classe.ClassName,TObject(classe));
      end;
    end;
     
    // Obtenir une classe par son nom
    function TForm1.getClassByName(nom: string): TMetaclass;
    var
      i : integer;
    begin
      // Recherche dans la liste des classByName
      i := ListofObj.IndexOf(nom);
      // si pas trouvé, on renvoie nil
      if (i = -1) then
      begin
        result := nil;
      end
      // si trouvé, on renvoie la classe associée
      else
      begin
        result := TMetaclass(ListofObj.objects[i]);
      end
    end;
     
    constructor TVoiture.create();
    begin
      ShowMessage('Voiture créée!');
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    var
     voiture : TVoiture;
    begin
      Vehicules := TObjectList.Create();
      ListofObj := TStringList.Create;
      registerClassByName(TVoiture);
      ListBox1.Items.Add('TVoiture')
    end;
     
    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      FreeAndNil(Vehicules);
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Vehicules.add(getClassByName(ListBox1.Items.Strings[ListBox1.ItemIndex]).Create());
    end;
     
    end.
    @+ Phil

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    109
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2002
    Messages : 109
    Points : 71
    Points
    71
    Par défaut
    Oui, j'avais ajouté directement TVoiture dans le composant TListBox.

    J'ai ajouté la clause override dans mon code original et ça fonctionne bien!

    Merci beaucoup de ton aide!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Classes et methodes, problème de référence
    Par Blue112 dans le forum Flash
    Réponses: 2
    Dernier message: 04/03/2007, 18h25
  2. [GRASP] Problème responsabilité d'une classe
    Par Royd938 dans le forum Design Patterns
    Réponses: 3
    Dernier message: 22/06/2005, 15h13
  3. [C#]Problème DirectX SDK & Sprite(Class)
    Par doccpu dans le forum DirectX
    Réponses: 3
    Dernier message: 16/06/2005, 13h30
  4. problème de références _ptr dans une map STL
    Par Mr_Tyu dans le forum CORBA
    Réponses: 1
    Dernier message: 10/08/2004, 10h39
  5. [MFC] Problème pointeur sur une classe
    Par mick74 dans le forum MFC
    Réponses: 7
    Dernier message: 14/04/2004, 14h17

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