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 :

Quelle est la différence entre ces deux déclarations ?


Sujet :

Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif  
    Inscrit en
    Mars 2006
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 352
    Par défaut Quelle est la différence entre ces deux déclarations ?
    Bonjour,

    voici une déclaration d'un prototype de procédure dans la section Type :
    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
    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
    
    type
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
        procedure calculer;
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.DFM}
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
    
    end;
    
    end.
    Et l'autre dans la section Type Private :
    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
    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
    
    type
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        { Déclarations privées }
        procedure calculer;
      public
        { Déclarations publiques }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.DFM}
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
    
    end;
    
    end.
    Quelle est la différence entre ces deux déclarations ?

    Merci d'avance.

  2. #2
    Membre chevronné
    Avatar de Hauwke
    Inscrit en
    Septembre 2005
    Messages
    329
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 329
    Par défaut
    Bonjour,
    La première déclaration est une méthode de la classe "TForm1". Pour faire simple, je dirai qu'elle va travailler quasi uniquement avec cette classe. D'ailleurs sa déclaration "normale" serait plutot :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     procedure Calculer(Sender : TObject);
    Cette méthode est liée à la classe "TForm1". Dés que vous allez créer une nouvelle classe dérivée de "TForm1" cette dernière héritera "naturellement" de la méthode "Calculer" (i.e si j'écris ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Type
     TMafenetre : Class(TForm1)
     end;
    J'aurai automatiquement accés à la méthode "calculer" de cette façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TMafenêtre.Faituntruc(sender :Tobject);
    begin
      with Mafennêtre do
      begin
          ...
          Calculer;
          ...
          end;
      end;
    La seconde déclaration est générale et plus restrictive! Plus générale parce qu'elle n'est pas liée à l'emploi d'un objet particulier, elle peut travailler de façon autonome et donc réaliser tout traitement de votre choix même si celà n'a aucun rapport avec votre objet "TForm1".
    Plus restrictive en effet, vos méthodes ne pourront l'utiliser qu'à la condition suivante:
    Elles doivent se trouver impérativement dans la même unité. De plus, même si vous utilisez cette unité au travers d'un autre module de votre programme (Inscription à la clause Uses) vous ne pourrez pas faire appel directement à cette méthode. Si je souhaite avoir accés à cette méthode depuis un autre module, je dois la déclarer dans la section publique.
    Cordialement,
    Hauwke

  3. #3
    Membre Expert
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Par défaut
    En fait de maniere plus generale les methodes et propriétés sont declarés dans 4 sections differentes, definissant ainsi leur portées :

    Private : Accessible uniquement depuis une methode de la classe elle meme.
    Protected : Accessible uniquement depuis une methode de la classe et de ses descendants
    Public : Accessible depuis n'importe quelle methodes ou procedure libre de n'importe quelle unités.
    Published : (essentiellement pour les propriétés) Idem Publique mais avec une compilation differente qui permet de conserver certaines information (RTTI) qui permettent au developpeur ou a L'IDE d'acceder a la liste, aux noms et aux types des propriétés.

    Quand a la section entre la definition de la classe et la section private, c'est une section definie comme publique
    Si je ne dit pas de betise, en fait toute methodes/Proprietes non associée a une section explicitement est definie comme publique.
    C'est a cet endroit que Delphi place la declaration des gestionaires d'evenements qu'il gere.
    De ce fait, je considere cette section comme la section réservées aux gestionaires d'evenements de Delphi, ce qui permet d'un coup d'oeil de savoir quels sont les evenements geres par delphi de ceux que l'on gere nous (affectation dynamique) qui se trouve dans la section publique, voir privée.

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

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Par défaut
    comme le dis clorish, c'est une section publique.
    Je pense qu'il ne faut rien mettre ici, c'est delphi qui se charge d'y placer les composants et les evenements crees à partir de l'ihm.
    D'ailleurs, je crois que si tu met une fonction dans cette section, delphi te dira gentilement qu'elle n'est pas associée a un evenement dans le dfm et te propose de la supprimer !

  5. #5
    Membre Expert
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Par défaut
    Citation Envoyé par guillemouze Voir le message
    Je pense qu'il ne faut rien mettre ici, c'est delphi qui se charge d'y placer les composants et les evenements crees à partir de l'ihm.
    Non ce n'est pas une obligation ... tout juste une recommandation
    Citation Envoyé par guillemouze Voir le message
    D'ailleurs, je crois que si tu met une fonction dans cette section, delphi te dira gentilement qu'elle n'est pas associée a un evenement dans le dfm et te propose de la supprimer !
    Du tout
    C'est le cas pour les procedures que delphi a ajouté automatiquement et que l'on supprime manuellement.
    En ce qui concerne les procedures que l'on cree nous meme, Delphi ne dit rien.
    Par contre, il supprime toutes declaration et implementation si celle ci est vide (ie strictement aucun caracteres entre le Begin et le End. un simple commentaire "//" permet d'eviter cet effet de bord).
    De ce fait, il est plutot recommandé de laisser cette section a Delphi

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 094
    Par défaut
    Entièrement d'accord avec Clorish, ce n'est juste qu'une histoire de visibilité ou portée de la méthode


    Citation Envoyé par Clorish Voir le message
    Si je ne dit pas de betise, en fait toute methodes/Proprietes non associée a une section explicitement est definie comme publique.
    Presque, par défaut, c'est public pour tout hérité de TObject, pour les hérités de TPersistent c'est published (heureusement d'ailleurs pour la DFM et les objets qui sont déclarés par défaut sous l'IDE)

    @Hauwke, on peut mettre une méthode publié sans pourtant que cela soit un gestionnaire d'évènement avec un objet Sender ... mais je crois que Paul TOTH, a déjà émis un avis à ce sujet

    ensuite

    Citation Envoyé par Hauwke
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure TMafenêtre.Faituntruc(sender :Tobject);
    begin
      with Mafennêtre do
      begin
          ...
          Calculer;
          ...
          end;
      end;
    Etrange, de mettre un singleton (soit volontaire pour les méthodes de classes cachant une instance, soit involontaire pour la var globale créée automatiquement pour chaque form) comme objet principal, alors qu'il semblerait souvent logique d'utiliser Self ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Membre Expert
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Presque, par défaut, c'est public pour tout hérité de TObject, pour les hérités de TPersistent c'est published (heureusement d'ailleurs pour la DFM et les objets qui sont déclarés par défaut sous l'IDE)
    Effecitvement, je me suis posé la question car les methodes evenements sont declarés dans le DFM par leur nom et je me suis dit que le seul moyen de les retrouver au chargement est d'utilier les RTTI

    Citation Envoyé par ShaiLeTroll Voir le message
    Etrange, de mettre un singleton (soit volontaire pour les méthodes de classes cachant une instance, soit involontaire pour la var globale créée automatiquement pour chaque form) comme objet principal, alors qu'il semblerait souvent logique d'utiliser Self ...
    En fait non. Vu le type de question j'en deduit que c'est un debutant en Delphi, voir en programmation orienté Objet.
    ET une des erreurs systematique des debutant (que j'ai faite pendant plusieurs mois .. .voir années ) est d'utiliser au sein de la classe l'instance ce cette classe declaré automatiquement par delphi.

    Ceci pour plusieurs raisons :
    1) La notion de classe et d'instance n'ets aps tres tres claire ....
    2) LE probleme d'utiliser la variable globale dans l'isntance ne se presente pas car en general une form est unique

    Pour ceux qui font l'erreur ou comprenne pas le pourquoi du comment, voici un petit exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Type
      TForm1 = Class(Tform)
      [...]
      End;
     
    Var Form1 : TForm1;
     
    Procedure TForm1.Fermer;
    Begin
    Form1.Close;
    End;
    Ce code ne semble pas poser de problemes sauf si on modifie la declaration suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Var Form1, Form1b : TForm1;
     
    Procedure UneProcedure;
    Begin
    Form1.Fermer;
    Form1b.Fermer;
    End;
    Dans ce cas : Form1.Fermer ferme Form1 .... et Form1b.Fermer ferme Form1 et non Form1b car on fait explicitement appel a Form1.Close dans la methode TForm1.Fermer ...

    Pour pouvoir utiliser plusieurs instances de la meme classe en affectant a chaque fois l'instance d'appel, on utilise self.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Procedure TForm1.Fermer;
    Begin
    Self.Close;
    End;
    Self vaut Form1 si on fait Form1.Fermer et vaut Form1b si on fait Form1b.Fermer

  8. #8
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 094
    Par défaut
    Citation Envoyé par Clorish Voir le message
    En fait non. Vu le type de question j'en deduit que c'est un debutant en Delphi, voir en programmation orienté Objet.
    sidahmed est un débutant, mais ma remarque pose sur le code de Hauwke, qui est Modérateur, donc son exemple qui contient la fonction Faituntruc, est un mauvais exemple (voir ma signature), comme tu l'as toi même expliquer dans ton message, l'utilisation abusive de la variable globale dans les méthodes de la form, où seul self doit y figurer, la variable globale devant être réservé pour les classes externe à la Form ou aux méthodes de classe de la form pouvant manipuler leur singleton ...

    Ensuite, pour la Gestion des Forms, la plupart du temps, on a qu'une seule fois une form ouverte ... voir La pour la gestion des form unique via la variable par défaut ou ICI voir comment encapsuler sa variable de form dans une méthode de classe, cela permet de comprendre l'objet, d'appréhender les concepts des design patterns ... et puis LA ou encore ICI, voilà, sidahmed, je te conseille de lire ses sujets, tu pourrais voir les questions que tout le monde se pose, et tu pourras te le poser et y répondre, ... n'hésite pas à faire les tuto sur comment créer des appli (genre la calculatrice windows) de A à Z, c'est très instructeur, j'ai pour ma part, commencé par le Tuto dans le bouquin de D4 fourni avec le CD
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Inactif  
    Inscrit en
    Mars 2006
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 352
    Par défaut
    Bonjour et merci à tous,
    Citation Envoyé par Hauwke Voir le message
    Bonjour,
    La première déclaration est une méthode de la classe "TForm1". Pour faire simple, je dirai qu'elle va travailler quasi uniquement avec cette classe. D'ailleurs sa déclaration "normale" serait plutot :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     procedure Calculer(Sender : TObject);
    Cette méthode est liée à la classe "TForm1". Dés que vous allez créer une nouvelle classe dérivée de "TForm1" cette dernière héritera "naturellement" de la méthode "Calculer" (i.e si j'écris ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Type
     TMafenetre : Class(TForm1)
     end;
    J'aurai automatiquement accés à la méthode "calculer" de cette façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TMafenêtre.Faituntruc(sender :Tobject);
    begin
      with Mafennêtre do
      begin
          ...
          Calculer;
          ...
          end;
      end;
    La seconde déclaration est générale et plus restrictive! Plus générale parce qu'elle n'est pas liée à l'emploi d'un objet particulier, elle peut travailler de façon autonome et donc réaliser tout traitement de votre choix même si celà n'a aucun rapport avec votre objet "TForm1".
    Plus restrictive en effet, vos méthodes ne pourront l'utiliser qu'à la condition suivante:
    Elles doivent se trouver impérativement dans la même unité. De plus, même si vous utilisez cette unité au travers d'un autre module de votre programme (Inscription à la clause Uses) vous ne pourrez pas faire appel directement à cette méthode. Si je souhaite avoir accés à cette méthode depuis un autre module, je dois la déclarer dans la section publique.
    Cordialement,
    Hauwke
    Maintenant, je veux utiliser une procédure déclarée dans Unit1 depuis une autre unité Unit2, j'ai écrit ce code :
    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
    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
    
    type
      TForm1 = class(TForm)
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
        procedure calculer;
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.DFM}
    procedure calculer;
    begin
    end;
    end.
    Et le code de l'unité Unit2 :
    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
    unit Unit2;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
    
    type
      TForm2 = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
    
    var
      Form2: TForm2;
    
    implementation
    
    uses Unit1;
    
    {$R *.DFM}
    
    procedure TForm2.FormCreate(Sender: TObject);
    begin
      calculer;
    end;
    
    end.
    Quand je compile le projet, j'aurai les erreurs suivants :
    [Erreur] Unit1.pas(14): Déclaration foreward ou external non satisfaite: 'TForm1.calculer'
    [Erreur fatale] Project1.dpr(6): Ne peut compiler l'unité utilisée 'Unit1.pas'
    Merci pour votre aide.

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

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    Citation Envoyé par Hauwke Voir le message
    Bonjour,
    La première déclaration est une méthode de la classe "TForm1". Pour faire simple, je dirai qu'elle va travailler quasi uniquement avec cette classe. D'ailleurs sa déclaration "normale" serait plutot :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     procedure Calculer(Sender : TObject);
    pourquoi donc ?!

    Citation Envoyé par Hauwke Voir le message
    La seconde déclaration est générale et plus restrictive! Plus générale parce qu'elle n'est pas liée à l'emploi d'un objet particulier, elle peut travailler de façon autonome et donc réaliser tout traitement de votre choix même si celà n'a aucun rapport avec votre objet "TForm1".
    plait-il ?!
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  11. #11
    Membre Expert
    Avatar de Clorish
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 474
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 474
    Par défaut
    [Erreur] Unit1.pas(14): Déclaration foreward ou external non satisfaite: 'TForm1.calculer'
    [Erreur fatale] Project1.dpr(6): Ne peut compiler l'unité utilisée 'Unit1.pas'
    Erreur classique : Tu as declaré la procedure Calculer mais tu ne l'a pas implementé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Procedure TForm1.Calculer;
    Begin
    // code
    End;
    Maintenant attention : Si unit1 a besoin de Unit2 (surement pour afficher la form suite a une action) et Unit2 a besoin de Unit1 (pour executer la methode calculer) tu as potentiellement une erreur de reference circulaire.
    Tu peux pour le moment y echapper car si au moins l'une des 2 unitee declare l'autre dans la liste des uses apres le mot clef "implementation".
    Mais une telle configuration est potentiellement dangeureuse car rapidement on arrive a devoir utiliser des objets ou faviables publiques des unitees, et donc d'etre obkiger de ramener la declaration de l'unitee dans la lsite des uses de la partie Interface. Et la on obtient la reference circulaire.

    Pour rester logique et propre, je conseille d'eviter un appel mutuel des 2 unites, et regroupper le code qui genere cet appel mutuel dans une classe situé dans une 3e unitee.
    Unit1 declare Unit2 pour afficher la form2
    Unit2 declare Unit3 pour executer la methode claculer
    Unit1 declare aussi Unit3 car si au depart on l'implemente dans Unit1 c'est qu'elle en a besoin (vraisemblablement).

    Ceci est petu etre avancé vu le niveau de la question, mais je pense qu'il est bon de le mentionner, histoire d'etre au courrant.
    "Un developpeur avertit en vaut deux"

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

Discussions similaires

  1. Quelle est la différence entre ces deux DSP?
    Par eclipse2007 dans le forum Signal
    Réponses: 2
    Dernier message: 17/02/2015, 19h26
  2. Quelle est la différence entre ces deux choses
    Par pierrot10 dans le forum jQuery
    Réponses: 3
    Dernier message: 26/01/2012, 11h37
  3. Quel est la différence entre ces deux écritures ?
    Par TocTocKiéLà? dans le forum C++
    Réponses: 5
    Dernier message: 06/08/2007, 14h11
  4. Réponses: 6
    Dernier message: 13/05/2007, 23h14
  5. [Conception] Quelle est la différence entre ces modèles ?
    Par ukanoldai dans le forum XML/XSL et SOAP
    Réponses: 1
    Dernier message: 10/01/2007, 16h17

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