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 :

Syntaxe : constructeur multiple


Sujet :

Langage Delphi

  1. #1
    Teo
    Teo est déconnecté
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2002
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 110
    Par défaut Syntaxe : constructeur multiple
    Bonjour

    Comment avoir plusieurs constructeur pour la meme classe ?
    Peuvent ils s'appeler mutuellement ?

    Dans mes fonctions j'ai pour habitude d'en faire une "GROSSE" (complexe),
    puis d'en faire des plus legeres qui l'appellent.
    Je souhaite faire de meme pour mon constructeur
    Expl Coté Déclaration
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Type 
    T_Ma_Classe = Class
     Private
      Composants...
     Public
      Constructor Create(Param_1,Param_2,Param_3:String);Overload;
      Constructor Create(Param_1,Param_3:String);Overload;//2eme Construct
      Constructor Create;Overload;//3eme construct
    Coté Implementation
    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
     
    Constructor T_Ma_Classe.Create(Param_1,Param_2,Param_3:String);
    Begin
      VCL1 := TVCL1.Create(Nil); 
      Bla bla....
    End;
     
    Constructor T_Ma_Classe.Create(Param_1,Param_3:String);
    Begin
      Create(Param_1,'Val_Param_2_Defaut',Param_3);
    End;
     
    Constructor T_Ma_Classe.Create
    Begin
      Create('Val_Param_2_Defaut','Val_Param_2_Defaut','Val_Param_3_Defaut');
    End;
    Le compilateur ne m'a rien dit, mais coté execution,
    n'aurais je pas des problemes ?
    du genre : si j'appelle le 3eme Construct,
    en fait j'aurais 2 instances en memoire, qui seront créées,
    A cause du Create qui est appelé comme une vulgaire methode "normale" ?

    Merci d'avance

  2. #2
    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
    Normalement ça ne pose pas de problème, pour exemple regarde l'implémentation de la classe TFileStream dans l'unité Classes.

    Tu remarqueras que le constructeur à deux paramètres fait appel au constructeur à trois paramètres à l'intérieur de son implémentation (et sans la présence du mot clé inherited )

  3. #3
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    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 081
    Par défaut
    Sinon les paramètres par défaut ça existe si les constructeurs font tous la même chose (semble que oui si appelle chaîné)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Type 
      T_Ma_Classe = Class
      Private
        Composants...
       Public
         Constructor Create(const Param_1:String = 'Val_Param_1_Defaut'; const const Param_2:String = 'Val_Param_2_Defaut'; const Param_3:String = 'Val_Param_3_Defaut');
    C'est marrant, j'ai corrigé la même chose dans le code d'un collègue, la semaine dernière qui malheureusement dans l'une des variantes ne transmettaient pas les paramètres, conséquence un bug, ... autant s'éviter de la maintenance !

    pour TFileStream, c'est particulier, car il y a un paramètre par défaut différent en fonction du sytème d'exploitation ... donc surcharge obligatoire ...
    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

  4. #4
    Expert confirmé

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Par défaut
    Non ce que tu veux faire est parfaitement légitime et fonctionne très bien. En fait, si un jour, au début de ton apprentissage du Delphi, tu as eu la fameuse violation d'accès sur l'exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    var
      List: TStringList;
    begin
      List.Create; // pas bien !
    end;
    Eh bien c'est lié.

    D'abord, je vais rappeler la différence entre méthode d'instance et méthode de classe. Une méthode d'instance est déclarée de façon "normale", et doit être appelée sur une instance :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    type
      TExample = class
      public
        procedure InstanceMethod(Param: Integer);
      end;
    ...
    var
      Example: TExample;
    ...
    Example.InstanceMethod(5);
    Cet appel transmet en fait deux paramètres à InstanceMethod : le premier paramètre réel est Example, associé au paramètre formel Self (sous-entendu) de type TExample. Le second est bien sûr 5 associé au paramètre formel Param.

    Une méthode de classe est déclarée avec le mot-clef class et doit (oui j'ai bien dit doit) être appelée sur une classe (en Delphi, une classe existe à l'exécution : leur type est appelé une métaclasse - voir tutoriel sur les métaclasses -, et généralement on peut y penser comme étant un pointeur sur un record particulier qui contient ses informations).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    type
      TExample = class
      public
        class procedure ClassMethod(Param: Integer);
      end;
    ...
    TExample.ClassMethod(5);
    Cet appel-ci transmet également deux paramètres à ClassMethod. Le premier réel est TExample, associé au paramètre formel Self, de type class of TExample cette fois ! Pour le second paramètre, 5 vs Param, pas de changement.

    Si maintenant vous faites l'appel (qui est accepté par le compilateur, malgré le doit sur lequel j'ai insisté plus tôt) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Example.ClassMethod(5);
    Que penses-tu qui est transmis pour le paramètre formel Self ? La réponse n'est pas Example, mais bien Example.ClassType. ClassType est une fonction déclarée dans TObject. C'est ce qu'on appelle en réalité un sucre syntaxique.

    Venons-en finalement aux constructeurs
    Tout comme pour les méthodes de classe, la syntaxe permet les deux formes d'appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    constructor Create(Param: Integer);
     
    TExample.Create(5);
    Example.Create(5);
    Cependant, contrairement aux méthodes de classes, ces deux formes ne sont pas sémantiquement équivalentes.

    En fait, un constructeur possède 2 paramètres formels invisibles. Le premier est toujours Self, dont je vais dire pour l'instant qu'il est de type Pointer. Le second, je l'appellerai SelfIsClass (mais il n'est pas possible d'y accéder via le code Delphi - en ASM inline oui, mais on n'est pas là), et est de type Boolean.

    Lorsqu'on fait l'appel :
    Celui-ci est transformé par le compilateur en l'appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TExample$Create(Pointer(TExample), True, 5);
    Si l'appel est sur un objet :
    Le code généré devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TExample$Create(Pointer(Example), False, 5);
    Ainsi, le paramètre formel SelfIsClass indique, comme son nom le suggère, si le paramètre Self contient une classe (True) ou un objet (False).

    Le début du code de tout constructeur (ce qui se passe dans le begin :p) pourrait être écrit (grossièrement, mais les détails sont hors sujet ici) en Delphi comme ceci (avec TExampleClass = class of TExample) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if SelfIsClass then
      TExample(Self) := TExampleClass(Self).NewInstance;
    Dès que le "begin est fini", Self contient donc toujours quelque chose qui est de type TExample (et non TExampleClass). Ainsi, pour le développeur, Self est de type TExample.

    Finalement, lorsque, dans le corps d'un constructeur, vous écrivez :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Create(5, 'Param par défaut');
    // ou même
    inherited Create(Param);
    Ces deux appels sont effectués, bien sûr, sur Self, donc sur un objet, et donc avec comme valeur de SelfIsClass la valeur False.

    Voilà, j'ai fini mon monologue J'espère que j'ai été clair
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  5. #5
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    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 081
    Par défaut
    Merci SJRD, c'est une très bonne explication : très intéressante !
    Cela a-t-il un lien avec TObject.InitInstance ?
    Tu devrais nous mettre ça dans un tuto genre "Les Coulisses de l'Objet Delphi"
    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

  6. #6
    Expert confirmé

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Merci SJRD, c'est une très bonne explication : très intéressante !
    Cela a-t-il un lien avec TObject.InitInstance ?
    Absolument : la méthode NewInstance appelle InitInstance, entre autres
    Citation Envoyé par ShaiLeTroll Voir le message
    Tu devrais nous mettre ça dans un tuto genre "Les Coulisses de l'Objet Delphi"
    Euh... Hum... En fait je suis en train d'écrire un livre là-dessus. Mais chuut ! C'est un secret (et en plus j'avance plus )
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  7. #7
    Teo
    Teo est déconnecté
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2002
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 110
    Par défaut
    MErci a tous

    Citation Envoyé par ShaiLeTroll
    Sinon les paramètres par défaut ça existe si les constructeurs font tous la même chose (semble que oui si appelle chaîné)
    J'y ai pensé mais comme par la suite les parametres seront de types differents, et il y aura des directives de compilations, j'ai opté pour prevoir le coup.
    Ca m'evitera de changer le prototype en cours de route.
    Ca fait un bail que je voulais utiliser de cette syntaxe, alors j'en profite pour me faire les dents.

    @Aka Guymelef
    Tu as raison, c'est tout a fait ca, le systeme evoluera dans cette direction.

    @sjrd
    La voilà une reponse quelle est chouette !explSi a mes debut, on m'avais tout expliqué comme ça !...
    "Sucre Syntaxique" J'adore - faut que je la resorte celle la
    J'aurais au moin cette raison pour me proqurer ton Book
    Ton explication est delicieuses(oui je suis un gourmand) : jai deja faim de ton livre - STOP au faillotage
    Grand merci - quand j'aurais des Violation d'acces, je saurais que cela ne vient pas de là : je perdrais donc moins de temps

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

Discussions similaires

  1. Object : Constructeur multiple
    Par Mistervanhalen dans le forum Général Python
    Réponses: 2
    Dernier message: 17/10/2008, 22h50
  2. Bonnes pratiques des constructeurs multiples
    Par TheDrev dans le forum C++
    Réponses: 6
    Dernier message: 05/05/2008, 19h06
  3. Syntaxe INSERT multiple MVS IBM
    Par freed201 dans le forum DB2
    Réponses: 5
    Dernier message: 16/04/2008, 18h55
  4. [Système] syntaxe stripslashes multiples
    Par Orb Dorb dans le forum Langage
    Réponses: 3
    Dernier message: 14/06/2007, 11h18
  5. interet des constructeurs multiples
    Par pseudobidon57 dans le forum Langage
    Réponses: 2
    Dernier message: 13/06/2007, 12h33

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