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 :

Héritage de TForm


Sujet :

Langage Delphi

  1. #1
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut Héritage de TForm
    Bonjour,

    Je rencontre le problème d'héritage suivant :

    J'ai créé une form que j'ai appelé w_Base
    Elle contient juste un bouton et un évènement clic de ce bouton

    J'ai créé une form que j'ai appelée w_Test2 et qui dérive de w_Base
    Pour la créer j'ai fait Fichier / Nouveau / Autre et j'ai délectionné dans l'onglet correspondant à mon projet w_Base
    Sur la nouvelle fenêtre j'ai surchargé l'évènement clic du bouton
    le code de la fenêtre est le suviant :
    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
    type
      Twin_Test2 = class(Twin_base)
        procedure Button1Click(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      win_Test2: Twin_Test2;
     
    implementation
     
    {$R *.dfm}
     
    procedure Twin_Test2.Button1Click(Sender: TObject);
    begin
      inherited;
      ShowMessage('test après héritage');
    end;
    Enfin dans la fenêtre principale j'ai appelé ma fenêtre de test
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure Twin_Appli.Button2Click(Sender: TObject);
    var
       LO_Form : TWin_Base;
    begin
        if LO_Form = Nil then LO_Form := TWin_Test2.Create(Application);
        LO_Form.Button1Click(Nil);
        LO_Form.Parent := Panel1;
        LO_Form.Visible := true;
    end;
    Ce que je ne comprends pas c'est qu'à l'ouverture l'évènement clic traite le code de l'objet parent (w_Base) et pas de celui qui en hérite (w_Test2) alors que LO_Form a été créé avec.

    si je remplace ma ligne par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TWin_Test2(LO_Form).Button1Click(Nil);
    effectivement cela fonctionne mais dans l'application que je veux construire ma procédure reçoit en paramètre une chaine de caractère indiquant la fenêtre à ouvrir.
    Je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      if Param = 'Test2' then LO_Form := TWin_Test2.Create(Application);
      if Param = 'xxx'     then LO_Form := TWin_xxx.Create(Application);
    et cela va multiplier les if et alourdir le code

    J'espère avoir été clair
    Merci de vos conseils

  2. #2
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 694
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 694
    Points : 13 130
    Points
    13 130
    Par défaut
    Il faut une méthode virtuelle pour que le polymorphisme opère.

    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
    type
      Twin_base = class(TForm)
        procedure Button1Click(Sender: TObject);
      private
        procedure Btn1Clicked; abstract; //ou virtual
      end;
     
      Twin_Test2 = class(Twin_base)
      private
        procedure Btn1Clicked; override
      end;
     
    procedure Twin_base.Button1Click(Sender: TObject);
    begin
      Btn1Clicked;
    end;
     
    procedure Twin_Test2.Btn1Clicked;
    begin
      ShowMessage('test après héritage');
    end;

  3. #3
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    Merci mais au niveau duquel des 3 modules je mets ce code ?

  4. #4
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 694
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 694
    Points : 13 130
    Points
    13 130
    Par défaut
    Mon exemple reprend tes noms de classe. Ce n'est pas assez clair ?

  5. #5
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    Si c'est très clair mais comme ça plante j'ai pensé que j'avais mal transcrit dans mon code

    procedure Btn1Clicked; abstract; //ou virtual. message les méthodes virtuelles doivent être abstraites ou dynamiques
    si j'écris ceci ça passe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    type
      Twin_base = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Déclarations privées }
        procedure Btn1Clicked; Virtual; Abstract;
      public
        { Déclarations publiques }
      end;
    procedure Btn1Clicked; override; message non trouvé dans la classe de base

  6. #6
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    Je viens d'essayer de déplacer "procedure Btn1Clicked; Virtual; Abstract;" soit dans Public soit dans le type.

    La compilation s'effectue bien mais cela plante à l'exécution avec une violation de mémoire


    type
    Twin_base = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Btn1Clicked; virtual; abstract;
    private
    { Déclarations privées }
    public
    end;

  7. #7
    Membre expérimenté Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Points : 1 448
    Points
    1 448
    Par défaut
    Citation Envoyé par Delphi-ne Voir le message

    procedure Btn1Clicked; abstract; //ou virtual. message les méthodes virtuelles doivent être abstraites ou dynamiques
    si j'écris ceci ça passe
    toute methode abstract doit etre virtual, sinon elle ne pourrait pas etre surchargée (ca aurait du etre implicite a mon avis, mais surement une incompatibilité lié au méthodes dynamic qui n'ont plus l'air d'être utiles).

    procedure Btn1Clicked; override; message non trouvé dans la classe de base
    ta procedure est en private.
    passe la en protected pour pouvoir la surcharger, mais dans ton cas il faut qu'elle soit publique vu qu'il faut que tu appelles cette methode depuis Twin_Appli

  8. #8
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    Voilà où j'en suis

    fenetre de base (celle dont héritent toutes les fenêtres)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    type
      Twin_base = class(TForm)
      private
        { Déclarations privées }
      public
        procedure test; virtual; abstract;
      end;
    fenêtre utilisation
    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
    type
      Twin_Test2 = class(Twin_base)
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
        procedure test;override;
      end;
     
    var
      win_Test2: Twin_Test2;
     
    implementation
     
    {$R *.dfm}
     
     
    procedure Twin_Test2.test;
    begin
      ShowMessage('test après héritage');
    end;

    Appel en dynamique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    var
       LO_Form : TWin_Base;
    begin
        if LO_Form = Nil then LO_Form := TWin_Test2.Create(Application);
        LO_Form.Parent := Panel1;
        LO_Form.Visible := true;
        LO_form.test;
    Aucune erreur.
    L'écran s'affiche bien mais quand je clique sur le bouton qui crée la fenêtre en dynamique j'ai une erreur de violation mémoire
    Sous debug c'est au niveau de la ligne LO_form.test;

  9. #9
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    Bonjour,

    La méthode Button1Click étant statique, son appel sur une variable de type TWin_Base donne bien un TWin_Base.Button1Click(), même si l'instance est de type TWin_Test2.

    Ce qu'il faut faire c'est invoquer le click du bouton

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    procedure Twin_Appli.Button2Click(Sender: TObject);
    var
       LO_Form : TWin_Base;
    begin
        if LO_Form = Nil then LO_Form := TWin_Test2.Create(Application);
        //LO_Form.Button1Click(Nil);
        LO_Form.Button1.Click(); // <- là c'est dynamique
        LO_Form.Parent := Panel1;
        LO_Form.Visible := true;
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  10. #10
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    J'ai commentarisé les autres essais
    J'ai saisi LO_Form.Button1.Click

    Toujours une violation mémoire

  11. #11
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    si LO_form est effectivement une variable locale sa valeur est indéfinie et pas forcément nulle.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    var
       LO_Form : TWin_Base;
    begin
        if LO_Form = Nil then // pas forcément vrai
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  12. #12
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    Oui mais le code de la méthode contient plusieurs lignes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        if LO_Form = Nil then LO_Form := TWin_Test2.Create(Application);
        LO_Form.Parent := Panel1;
        LO_Form.Visible := true;
        LO_Form.Button1.Click(); // <- là c'est dynamique
    Le plantage se passe sur le clic. Si l'objet n'était pas bien créé les lignes précédentes (parent et visible) planteraient.

  13. #13
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    je ne sais pas ce qui n'est pas bon dans ton code, voici un projet qui fonctionne

    temp.zip
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  14. #14
    Membre expérimenté Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Points : 1 448
    Points
    1 448
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    je ne sais pas ce qui n'est pas bon dans ton code, voici un projet qui fonctionne
    Bah je pense que tu as mis le doigt sur le problème dans ton message précédent.
    C'est pas parce que les 2 instructions avant ne font pas planter que le problème n'est pas là.
    Passe la variable locale LO_form en champ dans ta classe, et tout devrait fonctionner !

  15. #15
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    Effectivement cela fonctionne.
    J'ai intégré le code directement dans mon projet et cela va parfaitement
    Je vais chercher pourquoi dans mon projet d'essai Vendredi cela buggait.

    En tout cas vraiment merci beaucoup
    Le projet fini va compter un peu plus d'une cinquantaine d'écrans et cette approche va m'économiser beaucoup de code

  16. #16
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    si LO_form est effectivement une variable locale sa valeur est indéfinie et pas forcément nulle.
    Exact.
    La ligne de code suivante :
    ne retourne pas Nil même si la variable LO_Form n'a pas été initialisée
    le debugger ne permet pas de voir son contenu (optimisation de code)

  17. #17
    Membre expérimenté Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Points : 1 448
    Points
    1 448
    Par défaut
    Et tu dois même avoir un avertissement du compilateur
    la variable LO_form n'est peut être pas initialisée

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

Discussions similaires

  1. [Postgresql]Héritage
    Par lheureuxaurelie dans le forum PostgreSQL
    Réponses: 13
    Dernier message: 02/10/2008, 09h18
  2. [Postgres] Héritage + Clés
    Par k-reen dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 21/05/2003, 16h37
  3. [TForm] Ne pas autoriser l'ouverture d'un form
    Par sbeu dans le forum Composants VCL
    Réponses: 6
    Dernier message: 11/10/2002, 11h20
  4. Héritage entre Forms
    Par BarBal dans le forum Composants VCL
    Réponses: 7
    Dernier message: 29/08/2002, 17h44
  5. Probleme d'impression avec la méthode TForm->Print()
    Par Kid Icarus dans le forum C++Builder
    Réponses: 13
    Dernier message: 31/07/2002, 14h26

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