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

Langage Delphi Discussion :

Référence de classe (class of)


Sujet :

Langage Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 47
    Par défaut Référence de classe (class of)
    Soit une hiérarchie de 3 classes TTrois qui descend de TDeux qui descend de TUn.

    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
    unit uTestClassRef;
     
    interface
     
    uses
      SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs;
     
    type
      TRef2Class = class of TUn;
     
      TUn = class(TObject)
      private
        FDescription: string;
      public
        constructor Create;
        procedure Afficher; virtual; abstract;
      end;
     
      TDeux = class(TUn)
      public
        constructor Create(D: string = '');
        procedure Afficher; override;
      end;
     
      TTrois = class(TDeux)
      public
        constructor Create;
      end;
     
     
    implementation
     
    {
    ************************************* TUn **************************************
    }
    constructor TUn.Create;
    begin
      inherited Create;
      FDescription := 'Objet de classe TUn';
    end;
     
    {
    ************************************ TDeux *************************************
    }
    constructor TDeux.Create(D: string = '');
    begin
      inherited Create;
      FDescription := 'Objet de classe TDeux';
      if D <> '' then
        FDescription := D;
    end;
     
    procedure TDeux.Afficher;
    begin
      ShowMessage(FDescription);
    end;
     
    {
    ************************************ TTrois ************************************
    }
    constructor TTrois.Create;
    begin
      inherited Create('Objet de classe TTrois');
    end;
     
     
     
    end.
    Je désire les instancier à travers une référence de classe : TRef2Class = class of TUn comme ci-dessous:
    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
    unit uClassRefTest;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, uTestClassRef, StdCtrls;
     
    type
      TfmClassRef = class(TForm)
        btnT1parRef: TButton;
        btnT2parRef: TButton;
        btnT3parRef: TButton;
        btnT1Direct: TButton;
        btnT2Direct: TButton;
        btnT3Direct: TButton;
        procedure btnT3DirectClick(Sender: TObject);
        procedure btnT2DirectClick(Sender: TObject);
        procedure btnT1DirectClick(Sender: TObject);
        procedure btnT3parRefClick(Sender: TObject);
        procedure btnT2parRefClick(Sender: TObject);
        procedure btnT1parRefClick(Sender: TObject);
      private
        { Déclarations privées }
        procedure TestRef2Class(RC:TRef2Class);
      public
        { Déclarations publiques }
      end;
     
    var
      fmClassRef: TfmClassRef;
     
    implementation
     
    {$R *.dfm}
     
    procedure TfmClassRef.btnT2DirectClick(Sender: TObject);
    var
      Deux: TDeux;
    begin
      Deux := TDeux.Create;
      try
        Deux.Afficher;
      finally
        Deux.Free;
      end;
    end;
     
    procedure TfmClassRef.btnT2parRefClick(Sender: TObject);
    begin
      TestRef2Class(TDeux);
    end;
     
    procedure TfmClassRef.btnT3DirectClick(Sender: TObject);
    var
      Trois: TTrois;
    begin
      Trois := TTrois.Create;
      try
        Trois.Afficher;
      finally
        Trois.Free;
      end;
    end;
     
    procedure TfmClassRef.btnT3parRefClick(Sender: TObject);
    begin
      TestRef2Class(TTrois);
    end;
     
    procedure TfmClassRef.btnT1DirectClick(Sender: TObject);
    var
      Un: TUn;
    begin
      Un := TUn.Create;
      try
        Un.Afficher;
      finally
        Un.Free;
      end;
    end;
     
    procedure TfmClassRef.btnT1parRefClick(Sender: TObject);
    begin
      TestRef2Class(TUn);
    end;
     
    procedure TfmClassRef.TestRef2Class(RC: TRef2Class);
    var
      IRC: TUn;
    begin
      IRC := RC.Create;
      try
        (IRC as RC).Afficher;
      finally
        IRC.Free;
      end;
    end;
     
    end.
    Or chaque objet a un constructeur Create qui modifie la valeur d'un champ de TUn.
    Or c'est toujours la valeur affectée dans le constructeur de TUn qui est restituée par la méthode Afficher. Les valeurs affectées par les contructeurs de TDeux et TTrois ne sont jamais affectées lorsqu'on instancie ces classes à travers une référence de classe.
    Y a-t-il un moyen pour obtenir les messages corrects ?

  2. #2
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 947
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 947
    Billets dans le blog
    6
    Par défaut
    et avec
    (IRC as RC.ClassType).Afficher; ?
    mais dans ce cas, autant déclarer
    RC: TUn;
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  3. #3
    Membre Expert

    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    1 519
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 519
    Billets dans le blog
    1
    Par défaut
    Mmmh, moi j'aurai tendance à dire que c'est le transtypage avec la référence de classe derrière qui empêche le polymorphisme de fonctionner.

    Et si tu fais directement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure TfmClassRef.TestRef2Class(RC: TRef2Class);
    var
      IRC: TUn;
    begin
      IRC := RC.Create;
      try
        IRC.Afficher;
      finally
        IRC.Free;
      end;
    end;
    Qu'est-ce que ça donne ?

  4. #4
    Membre Expert

    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 897
    Par défaut
    C'est tout à fait normal dans ce cas prècis, car les construteurs de tes classes Tun, TDeux et TTrois sont statiques et donc le constructeur qui sera appelé sera toujours celui de la classe ancêtre.
    Il faut donc que tu les déclares les constructeurs "vitual" pour que la bonne méthode soit appelée.

    C'est la règle quant on utilise les références de class

    Apporte les petites modifications suivantes:

    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
    TRef2Class = class of TUn;
      TUn = class(TObject)
      private
        FDescription: string;
      public
        constructor Create; virtual;
        procedure Afficher; virtual;
      end;
      TDeux = class(TUn)
      public
        constructor Create; override;
        procedure Afficher; override;
      end;
      TTrois = class(TDeux)
      public
        constructor Create; override;
      end;
     
    implementation
     
    constructor TUn.Create;
    begin
      inherited Create;
      FDescription := 'Objet de classe TUn';
    end;
     
    constructor TDeux.Create;
    begin
      inherited Create;
      FDescription := 'Objet de classe TDeux';
    end;
     
    constructor TTrois.Create;
    begin
      inherited Create;
      FDescription := 'Objet de classe TTrois';
    end;
    Dans ce cas, ta procédure TestRef2Class t'affichera la bonne valeur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure TfmClassRef.TestRef2Class(RC: TRef2Class);
    var
      reference: TUn;
    begin
      reference := RC.Create;
      with reference do
      try
        Afficher;
      finally
        Free;
      end;
    end;

  5. #5
    Membre éprouvé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 47
    Par défaut
    Merci Pascal.
    J'avais bien pensé à cette solution, mais j'ai mis virtual dans les trois classes . J'avoue que j'ai toujours eu un peu de mal avec les constructeurs. En outre, en utilisant override, je ne peux pas utiliser un create avec paramètre dans la classe TDeux. Celà ne pose pas de problème dans le cas de l'exemple que j'ai soumis a votre sagacité, mais ce n'est qu'une version très simplifiée du code dans lequel je me suis heurté au problème, et dans lequel je crée et j'initialise de nouveaux champs dans les descendants.
    Encore merci à tous !

  6. #6
    Membre Expert

    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    1 519
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 519
    Billets dans le blog
    1
    Par défaut
    Dans ce cas cela devrait donner ceci :

    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
    type
      TRef2Class = class of TUn;
     
      TUn = class(TObject)
      private
        FDescription: string;
      public
        constructor Create; virtual;
        procedure Afficher; virtual; abstract;
      end;
     
      TDeux = class(TUn)
      public
        constructor Create(D: string = ''); virtual;
        procedure Afficher; override;
      end;
     
      TTrois = class(TDeux)
      public
        constructor Create; override;
      end;
     
     
    implementation
     
    {
    ************************************* TUn **************************************
    }
    constructor TUn.Create;
    begin
      inherited Create;
      FDescription := 'Objet de classe TUn';
    end;
     
    {
    ************************************ TDeux *************************************
    }
    constructor TDeux.Create(D: string = '');
    begin
      inherited Create;
      FDescription := 'Objet de classe TDeux';
      if D <> '' then
        FDescription := D;
    end;
     
    procedure TDeux.Afficher;
    begin
      ShowMessage(FDescription);
    end;
     
    {
    ************************************ TTrois ************************************
    }
    constructor TTrois.Create;
    begin
      inherited Create('Objet de classe TTrois');
    end;

  7. #7
    Membre émérite Avatar de Yurck
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    682
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 16
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2005
    Messages : 682
    Par défaut
    Citation Envoyé par erca57 Voir le message
    En outre, en utilisant override, je ne peux pas utiliser un create avec paramètre dans la classe TDeux.
    Mais si avec override tu peux mettre un paramètre à dans la classe TDeux.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    TDeux = class(TUn)
      public
        constructor Create(MonParametre : String); override;
        procedure Afficher; override;
      end;
     
    constructor TDeux.Create(MonParametre : String);
    begin
      inherited TUn.Create;
      FDescription := 'Objet de classe TDeux';
    end;

  8. #8
    Membre éprouvé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2007
    Messages : 47
    Par défaut
    Si je mets un paramètre au Create de TDeux, à la compilation j'obtiens le message :
    [Pascal Erreur] uTestClassRef.pas(27): E2037 La déclaration de 'Create' diffère de la déclaration précédente

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

Discussions similaires

  1. ArrayList<Class> class class.setString()
    Par Onelove dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 31/08/2014, 20h42
  2. Réponses: 4
    Dernier message: 26/12/2009, 21h48
  3. Réponses: 4
    Dernier message: 25/06/2009, 12h40
  4. Utiliser une référence dans une classe
    Par Davidbrcz dans le forum C++
    Réponses: 4
    Dernier message: 07/01/2007, 21h13
  5. Réponses: 10
    Dernier message: 24/09/2005, 20h19

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