FAQ PascalConsultez toutes les FAQ
Nombre d'auteurs : 10, nombre de questions : 402, dernière mise à jour : 7 janvier 2018 Ajouter une question
Bienvenue dans la F.A.Q. Pascal !
Celle-ci rassemble les réponses aux questions les plus fréquemment posées sur le langage Pascal et tous ses outils de programmation. Si elle n'a pas pour vocation de répondre à toutes les interrogations possibles, elle reste une bonne base de connaissances sur le Pascal, et ne demande qu'à être enrichie par vos expériences personnelles.
Nous vous invitons à proposer vos propres questions/réponses directement dans la FAQ ou, si vous souhaitez apporter une modification à une question/réponse existante, à la poster dans le fil de discussion renseigné ci-dessous.
Nous vous souhaitons une bonne lecture !
L'équipe Pascal.
- Qu'est-ce qu'un constructeur ?
- Comment disposer de plusieurs constructeurs ?
- Quand faut-il hériter dans un constructeur ?
- Comment gérer une erreur lors de l'instanciation d'une classe ?
- Qu'est-ce qu'un destructeur ?
- Pourquoi et comment libérer un objet après son utilisation en Pascal ?
- Quand faut-il hériter dans un destructeur ?
- Pourquoi ne faut-il pas utiliser Destroy pour détruire une instance de classe ?
- A quoi sert Nil pour un objet ?
- Peut-on libérer un objet par une simple affectation à Nil ?
- Comment s'assurer qu'une instance de classe sera toujours libérée ?
- Quand faut-il faire appel à la procédure FreeAndNil ?
Un objet en tant qu'instance de classe occupe de la mémoire qu'il faut allouer sur le tas (heap) avant toute utilisation le concernant. Un constructeur (constructor) est précisément une méthode spéciale qui permet cette allocation de mémoire tout en renvoyant un pointeur vers l'objet créé.
En général, cette méthode particulière s'appelle Create, mais ce nom est arbitraire. En revanche, sa déclaration commencera toujours par le mot réservé constructor. Il peut exister plusieurs constructeurs avec autant de paramètres que nécessaires.
Voici le code pour la création de l'objet MyObjde type TMyClasssi l'un de ses constructeurs s'appelle Createet ne prend aucun paramètre :
Code pascal : | Sélectionner tout |
1 2 |
MyClass := TMyClass.Create; |
N.B. : C'est toujours en mentionnant le nom de la classe (ici, TMyClass) que l'on crée un objet.
Il peut arriver aussi que vous ayez besoin de plusieurs constructeurs pour une même classe. Dans ce cas, c'est la directive overload qui sera utile puisqu'elle permet des homonymes aux paramètres différents.
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 7 | type TMyClass = class public constructor Create; overload; constructor Create(const ASt: string); overload; end; |
Il est exceptionnel de ne pas avoir à surcharger un constructeur : la plupart du temps, il faut initialiser des champs à des valeurs spécifiques ou instancier certaines classes qui serviront d'outils. Mais il faut aussi conserver d'éventuelles initialisations des constructeurs des ancêtres, d'où la nécessité d'employer inherited.
Si vous voulez modifier le comportement des parents, il est généralement nécessaire d’appeler en premier lieu inherited puis d’apporter les modifications.
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 | constructor Create; begin inherited Create; // on hérite // ensuite votre travail d’initialisation // [...] end; |
En cas d'erreur lors de l'instanciation, le destructeur Destroy correspondant est automatiquement appelé.
La conséquence majeure de ce mécanisme est qu'il ne faut pas protéger le code de l'instanciation au risque d'essayer de libérer plusieurs fois des ressources :
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // code fautif try MyObj := TMyClass.Create; MyObj.DoSomething; finally MyObj.Free; end; // code correct MyObj := TMyClass.Create; try MyObj.DoSomething; finally MyObj.Free; end; |
Comme un objet occupe de la place en mémoire, il est nécessaire de la libérer après usage. Cette libération peut être automatique dans certains cas (comme avec des composants posés sur une fiche), mais demande la plupart du temps une action explicite du programmeur. C'est cette libération de la mémoire que réalise un destructeur.
Le destructeur (destructor) est une méthode particulière dont le nom est toujours Destroy. Il est déclaré avec le mot réservé destructoret ne ne comporte aucun argument.
Voici un exemple de déclaration d'un destructeur :
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 | TMyClass = class [...] public constructor Create(AValue: Integer); destructor Destroy; override; end; |
Le destructeur n'est pas appelé directement, mais via la méthode Free. On surcharge le destructeur afin d'être sûr de ne pas oublier d’appeler le destructeur des ancêtres de la classe en question.
Quand vous n'avez plus besoin d'un objet, il est nécessaire de le détruire, sinon vous obtiendrez ce qu'on appelle des fuites de mémoire : la mémoire allouée à votre objet ne sera pas libérée par le système.
Pour le libérer, il suffit d'appeler la méthode Freequi fera le travail nécessaire.
Exemple :
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 7 8 | var MyClass: TMyClass; [...] MyClass := TMyClass.Create; [...] MyClass.DoSomething; [...] MyClass.Free; |
N.B. : la méthode Freeest disponible dès l'instanciation de votre classe.
Pour Destroy, le schéma suivant s’applique : procédez en premier lieu à votre travail local de nettoyage (en général, la libération d'objets créés par votre classe pour ses besoins propres) puis héritez de l'ancêtre. Sinon, vous risquez par exemple de vouloir libérer des ressources qui auront déjà été libérées par un ancêtre de votre classe et par conséquent de provoquer une erreur.
La forme habituelle du destructeur Destroy hérité sera donc :
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 | destructor Destroy; begin // votre travail local de nettoyage // [...] inherited Destroy; // on hérite ensuite ! end; |
Il peut sembler paradoxal de renseigner la méthode Destroy pour détruire un objet, mais d'appeler la méthode Free pour le faire.
En fait, la méthode Free vérifie l'existence de l'objet avant de la le détruire, ce qui évite de déclencher une erreur si l'objet n'a pas été créé correctement : en effet, comment détruire un objet qui n'a pas été créé ? Après cette vérification, Free appelle Destroy.
Nilest la valeur attribuée à un objet lorsqu'il n'a pas encore été créé. Il est ainsi possible de tester la valeur de la variable renvoyant à l'hypothétique objet.
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 | var MyObj: TMyClass; [...] if MyObj = nil then MyObj := TMyClass.TCreate; |
N.B. : un équivalent de ce test est l'emploi de la méthode Assigned.
On peut par conséquent écrire :
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 | var MyObj: TMyClass; [...] if not Assigned(MyObj) then MyObj := TMyClass.TCreate; |
Il peut être tentant de libérer un objet en lui affectant la valeur Nilpuisqu'elle correspond à un objet non affecté. Malheureusement, cette affectation ne libèrera pas la mémoire allouée à l'objet : il faut par conséquent utiliser la méthode Freeou la procédure FreeAndNil.
N.B. : comme son nom l'indique FreeAndNillibère en premier lieu l'objet puis met à Nilsa valeur.
Afin de s'assurer que la mémoire allouée à une instance de classe sera toujours libérée, il suffit d'utiliser try...finally.
Exemple :
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | var MyObj: TMyClass; [...] MyObj := TMyClass.Create; try MyObj.DoSomething; finally MyObj.Free; end; |
N.B. : La création de l'objet a lieu en dehors de la section protégée, car en cas d'échec de Create, la mémoire pour l'objet n'est pas réservée.
Si vous pensez réutiliser une variable référençant une instance de classe libérée, en lieu et place de Free, utilisez la procédure FreeAndNil définie dans SysUtils qui à la fois libère l'instance comme Free, mais aussi place la valeur nil dans le pointeur sur cette instance.
De cette manière, la méthode Assigned ne sera pas leurrée par la destruction d'un objet qui ne réinitialise pas la référence à cette instance !
Au lieu de :
Code pascal : | Sélectionner tout |
MyObj.Free;
vous pouvez uitliser
Code pascal : | Sélectionner tout |
FreeAndNil(MyObj);
N.B. : L'utilisation de la procédure FreeAndNil est déconseillée par certains, car elle est souvent le signe d'une mauvaise conception d'un programme : une instance libérée ne devrait jamais être réutilisée.
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.