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 :

[Delphi 2009] inherited dans les exemples


Sujet :

Langage Delphi

  1. #1
    Membre émérite
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 401
    Points : 2 304
    Points
    2 304
    Par défaut [Delphi 2009] inherited dans les exemples
    Salut;

    Ayant un habitué de D7 et voulant passer à Delphi 2009 ou 2010, je commence tout naturellement par lire les exemples fournis. Le code du projet gdsdemo a attiré mon attention sur le fait de l'emploi (abusif à mon avis) de la méthode inherited dans pratiquement toutes les procédures.

    Pour mieux comprendre ce que j'essaie de vous dire voici un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    procedure TStdDataForm.FormCreate(Sender: TObject);
    begin
      inherited;
      FLastDate := EncodeDate(1995, 1, 1);
      FLastAmount := 1000;
      FilterOnRadioGroup.ItemIndex := 0;
    end;
    Alors pour voir la différence j'enlève inherited de toutes les procédure rien que pour avoir une idée, après compilation ça semble fonctionner à merveille, donc qu'apporte l'ajout de inherited ? sachant aussi que cette exemple marche bien sous la version D7 où on ne vois pas inherited dans le code.

    Des explications à ça ?! merci d'avance.
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  2. #2
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    rien du tout, on se demande même pourquoi le compilo ne mets pas une grosse claque dans la tête de celui qui fait ça.


    les gestionnaires d'évènements dans les fiches, sont censé être "unique" et non "héritable".

    y ajouter un inherited et donc tout simplement une abération.

    considérer qu'il est possible de le faire, reviens à considérer que la classe TForm possède déjà un gestionnaire d'évènements FormCreate ou autres, déjà assigné à sa propriété privée fOnCreate et qui ne serait pas écrasée à l'assignation de notre propre gestionnaire d'évènement, ce qui est bien sur, impossible.

    inherited ne sert uniquement qu'aux méthodes pouvant être héritées donc présente dans l'une des classes ancêtre de la classe sur laquelle on travail.

    par exemple, le constructeur de la classe "class" ne nécessite pas d'inherited car il n'existe pas de constructeur Create dans Class!

    mais une méthode héritée ne necessite pas obligatoirement d'appeler la méthode ancêtre!
    dans un objet dérivé de TGraphicControl par exemple, il n'est pas obligatoire d'appeler Inherited dans la méthode Paint surchargée.

    dans les create ou les destroy, il n'est pas necessaire non plus de le faire si on utilise nos propres routines de gestion de la memoire et des instances d'objets!


    pour aller plus loin :

    prenont par exemple un objet de type TObject dont on aurait surchargé la methode Create.
    voici ce qu'il se passe en memoire quand on crée une instance TMonObject :

    allocation de memoire adresse M pour une instance de taille TMonObject
    création d'une instance de type Class
    création la surcharge de Class par le type TObject
    création la surcharge de TObject par le type TMonObject

    explication :
    TObject necessite inherited pour acceder au éléments surchargé de Class
    TMonObject necessite inherited pour acceder au éléments surchargé de TObject et Class

    ce qui permet de transtyper TMonObject autant qu'en TObject qu'en Class.

    la magie de la POO et du polymorphisme.

    dans le cas d'un gestionnaire d'evenement, il n'y a pas de mecanisme de surcharge de ce dernier.
    un gestionnaire d'evenement se présente comme cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    type
      TExemple = class
      private
        fOnTruc : TNotifyEvent;
      protected
        procedure DoTruc; virtual; { code > if assigned(fOnTruc) then fOnTruc(Self); }
      published
        property OnTruc : TNotifyEvent read fOnTruc write fOnTruc;
    ici on voit que OnTruc lit et ecrit une seule adresse de variable : fOnTruc.
    tout gestionnaire précédement assigné à OnTruc sera remplacé par la nouvelle assignation.
    tout comme quand on assigne une valeur à une variable N :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    N := 0 // N égal 0
    N := 1 // N est maintenant égal à 1, la valeur 0 est perdue.
    il est donc impossible de pouvoir accéder à une ancien gestionnaire puisque son adresse à été perdue.

    par contre, ici on peu voir la méthode "DoTruc", marquée Virtual, ce qui permet de la surcharger et donc de faire figurer inherited dans sa surcharge, exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    type
      TNouvelExemple = class(TExemple)
      protected
        procedure DoTruc; override;
      end;
     
    procedure TNouvelExemple.DoTruc;
    begin
      { faire quelque chose avant }
      inherited;
      { faire quelque chose aprés }
    end;
    voila.
    [ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
    Ma messagerie n'est pas la succursale du forum... merci!

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 128
    Points
    13 128
    Par défaut
    Citation Envoyé par Dr.Who Voir le message
    rien du tout, on se demande même pourquoi le compilo ne mets pas une grosse claque dans la tête de celui qui fait ça.
    Ce qui correspondrait à une auto-flagellation puisque c'est l'IDE lui-même qui le rajoute .

    Citation Envoyé par Dr.Who Voir le message
    les gestionnaires d'évènements dans les fiches, sont censé être "unique" et non "héritable".
    Mais ils le sont, ce ne sont que des variables. Donc forcément uniques et non-héritables.

    Citation Envoyé par Dr.Who Voir le message
    considérer qu'il est possible de le faire, reviens à considérer que la classe TForm possède déjà un gestionnaire d'évènements FormCreate ou autres, déjà assigné à sa propriété privée fOnCreate et qui ne serait pas écrasée à l'assignation de notre propre gestionnaire d'évènement, ce qui est bien sur, impossible.
    Tu mélanges deux choses, la variable procédurale et la procédure elle-même. Bien-sûr que FOnCreate pointera sur la dernière méthode affectée, mais cette dernière peut très bien exécuter une procédure de la classe ancêtre. Dans le cas du OnCreate et d'un héritage de fiche (puisque c'est de cela qu'il s'agit), mes deux fiches ont (ou pourraient avoir) une procédure FormCreate !

    Citation Envoyé par Dr.Who Voir le message
    inherited ne sert uniquement qu'aux méthodes pouvant être héritées...
    Faux si pour toi ça implique que la procédure soit virtual !
    inherited sert à exécuter une procédure dans la classe ancêtre, peu importe qu'elle soit virtuelle ou pas !

    Bien sûr qu'on pourrait surcharger le constructeur, mais pourquoi ne pourrait-on pas redéfinir FormCreate ? Un double-click dans l'inspecteur d'objet est tellement plus simple .

  4. #4
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Ce qui correspondrait à une auto-flagellation puisque c'est l'IDE lui-même qui le rajoute .
    et bien dis à ton IDE d'arreter de boire. placer un inherited dans un gestionnaire d'evenement n'est pas une bonne façon de faire.
    il faut plutôt agir de préférence sur la méthode qui appel la variable evenement.


    Citation Envoyé par Andnotor Voir le message
    Tu mélanges deux choses, la variable procédurale et la procédure elle-même. Bien-sûr que FOnCreate pointera sur la dernière méthode affectée, mais cette dernière peut très bien exécuter une procédure de la classe ancêtre. Dans le cas du OnCreate et d'un héritage de fiche (puisque c'est de cela qu'il s'agit), mes deux fiches ont (ou pourraient avoir) une procédure FormCreate !
    comme dit plus haut, ce n'est pas la bonne façon de faire.
    les gestionnaire d'evenement sont censé être RAD et donc doivent contenir un minimum de chose.
    Il est vrai qu'il est possible de le faire, mais c'est une mauvaise méthode.
    en aucun cas le developpeur final (celui qui utilise un composant) ne devrait ce soucier des héritages dans les composant.



    Citation Envoyé par Andnotor Voir le message
    Faux si pour toi ça implique que la procédure soit virtual !
    inherited sert à exécuter une procédure dans la classe ancêtre, peu importe qu'elle soit virtuelle ou pas !
    tout a fait, mais cela reste dans des cas précis, par respect des conventions, on evitera au maximum de surcharger les methodes non marquée virtual ou dynamic.
    par contre il est effectivement possible d'appeler une methode ancêtre via inherited, mais il n'est pas necessaire d'appeler inherited si cette methode est publique et non surchargée.
    ce cas restera donc "réservé" aux createurs de composant qui savent jongler avec ce genre de choses, tout comme le mots inherited ne devrait être utiliser que par le developpeur de composant et son rôle est justement d'eviter au développeur final de ne pas ce soucier de l'héritage.

    ici le cas etait d'appeler inherited seul, donc d'appeler une methode identique dans la classe ancêtre et donc supposée être surchargée par la nouvelle methode. toujours par respect des conventions on passera plutot par une methode virtuelle ou dynamique plutot que de surcharger une méthode qui ne doit pas l'être.


    Citation Envoyé par Andnotor Voir le message
    Bien sûr qu'on pourrait surcharger le constructeur, mais pourquoi ne pourrait-on pas redéfinir FormCreate ? Un double-click dans l'inspecteur d'objet est tellement plus simple .
    [/QUOTE]

    parce que comme dis plus haut, c'est une mauvaise façon de faire et ce n'est pas respectueux des conventions d'ecriture d'objet.
    les surcharges explicite (donc de methode virtuelle ou dynamique) sont considérée comme fiable. par contre les surcharges implicite (de methode non prévue pour la surcharge) ne sont pas considérées comme fiable.

    donc comme "tout ce que la loi ne prevoit pas n'est pas forcement un droit aquis", on fera l'analogie avec "tout ce que le compilateur permet n'est pas forcement une bonne façon de faire".

    les conventions sont créer en fonction des capacités et possibilités du compilateur. les respecter permet de faciliter l'optimisation du code par le compilo. aller au dela de ces conventions est rarement bénéfique.

    et ne jamais oublier qu'un composant doit toujours faciliter la vie du developpeur final. devoir le confronter aux inherited ou lui imposer ces derniers, n'est pas dans l'esprit RAD.
    Tout doit être transparent dans l'utilisation d'un composant.

    par contre, effectivement, libre au developpeur final d'appeler une methode ancêtre dans le composant dérivé.
    mais ce choix doit être laissé à lui et à lui seul.
    [ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
    Ma messagerie n'est pas la succursale du forum... merci!

  5. #5
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Salut,

    Drôle de débat :\

    Ne suffit t il pas de supprimer les "inherited" collés par l'IDE le cas échéant :\
    Akim Merabet

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 128
    Points
    13 128
    Par défaut
    Il ne s'agit pas de composants installés dans la palette mais du cas particulié que représente l'héritage de fiche dans Delphi, implicite dans le projet en cours ou par référenciel.

    En aucun cas, je ne parle de fournir des fiches "prémachées" à une tiers personne, mais bien d'accélérer son propre développement .

  7. #7
    Membre émérite
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 401
    Points : 2 304
    Points
    2 304
    Par défaut
    Citation Envoyé par Kaféine Voir le message
    Salut,

    Drôle de débat :\

    Ne suffit t il pas de supprimer les "inherited" collés par l'IDE le cas échéant :\
    Pourquoi ?
    si Embarcadero a trouvé que c'est juste de le rajouter c'est qu'on doit savoir la raison, non ? plutôt que d'aller vers les solutions simples (suppression en l'occurrence )
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  8. #8
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Salut,

    Citation Envoyé par Just-Soft
    Pourquoi ?
    si Embarcadero a trouvé que c'est juste de le rajouter c'est qu'on doit savoir la raison, non ? plutôt que d'aller vers les solutions simples (suppression en l'occurrence )
    Ce que je voulais dire c'est que c'est au choix du développeur d'appeler le inherited ou pas. L'IDE le met automatiquement pour des raisons de productivité.

    Par exemple imaginons 1 Form de base et 1 form descendante de cette form de base.
    La form de base défine le FormCreate. A ce stade, pas de inherited dans le gestionnaire d'evénement.
    La form descendante redéfinit le FormCreate et ici l'IDE colle un inherited. Ensuite libre au développeur de le supprimer s'il ne veut pas appeler le FormCreate du parent. Ca évite de la taper :\
    Enfin c'est ce que j'imagine mais je peux me tromper.

    PS: Dans le cas ou la form de base ne définit pas de FormCreate, le compilateur ignore simplement le inherited de la form descendante.
    Akim Merabet

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 149
    Points : 61
    Points
    61
    Par défaut
    Je pense que Kaféine et Andnotor ont bien résumé la chose :

    Ces "inherited" ne sont pas là pour faire beau mais pour éviter des "oublis" lorsqu'on faire de l'héritage de fiche.

    Quand on surchage (mais aussi souvent quand on redéfinit) une méthode dans une classe on trouve logique que le compilateur nous intègre "inherited" par défaut pour des raisons de productivité. En effet la logique objet fait que par défaut un fils hérite du comportement du parent...
    Il est donc logique d'avoir également cette approche dans les gestionnaires tout comme dans les méthodes de message, je ne suis donc pas d'accord avec Dr. Who.


    PS : gros déterrage de topic, désolé je viens de m'en rendre compte. Tant pis je poste quand même ! pour faire vivre un peu plus le forum

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 149
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par ZZZzzz2 Voir le message
    Je pense que Kaféine et Andnotor ont bien résumé la chose :

    Ces "inherited" ne sont pas là pour faire beau mais pour éviter des "oublis" lorsqu'on faire de l'héritage de fiche.

    Quand on surchage (mais aussi souvent quand on redéfinit) une méthode dans une classe on trouve logique que le compilateur nous intègre "inherited" par défaut pour des raisons de productivité. En effet la logique objet fait que par défaut un fils hérite du comportement du parent...
    Il est donc logique d'avoir également cette approche dans les gestionnaires tout comme dans les méthodes de message, je ne suis donc pas d'accord avec Dr. Who.


    PS : gros déterrage de topic, désolé je viens de m'en rendre compte. Tant pis je poste quand même ! pour faire vivre un peu plus le forum

    D'ailleurs j'en oublie la raison pour laquelle j'ai atterri sur ce sujet et pourquoi je voulais y poster un message.

    Depuis quelques temps on peut définir des constructeurs de classes (principalement l'idée est d'y initialiser les variables de classes) et j'ai découvert qu'on pouvait utiliser le mot clé inherited, mais que celui-ci n'avait pas d'utilité. Car lorsqu'on créé une classe Y qui dérive de X, la classe X est forcément créée également et donc son constructeur est appelé. Cela est lié je pense au fonctionnement des variables de classe qui ne peuvent êtres "virtuelles" (au sens qu'on aurait une instance par classe "finale"/"dérivée" et non uniquement dans la classe où elle est déclarée. La logique est la même pour les classes génrériques à la différence qu'on a une classe par type paramétré définie), en tout cela est cohérent.

    On a donc ici un comportement différent des instances qui peuvent ou non "choisir" de réaliser l'initialisation du parent ou non.
    Ce qui m'étonne c'est qu'on puisse quand même utiliser le mot-clé "inherited" alors que celui-ci semble ne servir à rien, ce qui apporte un peu de confusion je trouve.

    Qu'en pensez-vous ? Ou ai-je mal compris quelque-chose ?

Discussions similaires

  1. Absence de fichiers dans les exemples
    Par mga_geo dans le forum IGN API Géoportail
    Réponses: 11
    Dernier message: 04/03/2010, 12h21
  2. Indy 10.5.5 + Delphi 2009 -> accents dans corps d'email.
    Par Lux interior dans le forum API, COM et SDKs
    Réponses: 0
    Dernier message: 26/03/2009, 10h06
  3. Réponses: 3
    Dernier message: 06/07/2007, 09h49
  4. [Delphi 2007] Où sont les Démos dans Delphi 2007
    Par renepuyhaub dans le forum Delphi
    Réponses: 2
    Dernier message: 21/04/2007, 09h51
  5. Réponses: 6
    Dernier message: 19/06/2006, 10h43

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