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'une méthode en Pascal ?
- D'où proviennent des méthodes comme Free et Create alors qu'elles ne sont pas déclarées par le programmeur ?
- Qu'appelle-t-on une méthode statique ?
- Qu'appelle-t-on une méthode virtuelle ?
- A quoi sert le mot réservé inherited ?
- A quoi sert la directive override ?
- Qu'est-ce qu'une méthode marquée dynamic ?
- A quoi sert la directive reintroduce ?
- Qu'est-ce qu'une méthode abstraite ?
- Quand utiliser une classe qui comprend des méthodes abstraites ?
- Qu'est-ce qu'une méthode de classe ?
- Qu'est-ce qu'une méthode statique de classe ?
Une méthode décrit des opérations applicables grâce à une classe. Elle est soit une procédure soit une fonction encapsulée dans une classe. L'accès à une méthode suit le schéma suivant :
Code pascal : | Sélectionner tout |
NomDeLObjet.NomDeLaMethode
Notez que pour être utilisée, une méthode ordinaire doit appartenir à une classe qui a été instanciée. Autrement dit, la première partie de l'expression, celle qui précède le point, doit être un objet valide.
Exemple :
Code pascal : | Sélectionner tout |
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 | interface type TMyClass = class private fMyInt: Integer; public function DoubleInt: Integer; property MyInt: Integer read fMyInt write fMyInt; end; implementation function TMyClass.DoubleInt; begin Result := MyInt * 2; end; [...] var MyObject: TMyClass; I: Integer; [...] MyObject := TMyClass.Create; MyObject.MyInt := 4; I := MyObject.DoubleInt; // I vaut 2 fois 4 = 8 [...] MyObject.Free; |
Les méthodes comme Free et Create ne sont pas déclarées par vous et vous pouvez cependant les utiliser. Ce phénomène paraît contredire le principe pascalien qui veut que tout identificateur doit être déclaré avant de pouvoir être utilisé.
En fait, toute classe déclarée hérite d'une classe racine baptisée TObject. C'est cette dernière qui déclare et implémente ces méthodes mystérieuses.
Ainsi :
Code pascal : | Sélectionner tout |
1 2 3 4 | type TMyClass = class [...] end; |
et :
Code pascal : | Sélectionner tout |
1 2 3 4 | type TMyClass = class(TObject) [...] end; |
sont deux écritures équivalentes.
Les méthodes statiques se comportent comme des procédures ou des fonctions ordinaires à ceci près qu’elles ont besoin d’un objet pour être invoquées. Elles sont dites statiques parce que le compilateur crée les liens nécessaires à leur accès dès la compilation : elles sont ainsi particulièrement rapides, mais manquent de souplesse en se refusant à tout polymorphisme. Pour les utiliser, il suffit de les déclarer, sans autre précision.
Une méthode statique peut être redéfinie dans les classes qui en héritent.
Dans l'exemple suivant, la méthode DoSomething sera statique :
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | type TMyClass = class public procedure DoSomething; end; [...] implementation procedure TMyClass.DoSomething; begin Beep; Sleep(200); Beep; end; |
Contrairement aux méthodes statiques dont le compilateur détermine directement les adresses au moment de la compilation, les méthodes virtuelles sont accessibles via une table qui porte le nom de VMT (Virtual Method Table, soit table des méthodes virtuelles). C'est elle qui permet de retrouver à l’exécution l'adresse de chacune des méthodes dont la classe a hérité et de celles qu’elle a elle-même définies.
Une méthode virtuelle autorise la mise en œuvre du polymorphisme. Pour la déclarer, il faut faire suivre sa déclaration de la directive virtual. Pour la redéclarer dans une sous-classe, il faut faire suivre sa déclaration de la directive override.
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | type TMyClass = class public MyProc(AValue: string); virtual; end; TMySubClass = class(TMyClass) public MyProc(AValue: string); override; end; |
Les méthodes virtuelles sont particulièrement intéressantes lorsque vous ignorez quels objets vont être précisément activés à l'exécution.
Le mot réservé inherited permet d’hériter du comportement d'une méthode d’un parent tout en autorisant des compléments.
Dans l'exemple suivant, si TChien descend de TAnimal, l'appel à la méthode Manger de TChien affichera 'Je mange... mais principalement de la viande !' :
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | procedure TAnimal.Manger; begin writeln('Je mange.'); end; procedure TChien.Manger; begin inherited Manger; // on hérite de la méthode du parent writeln('.. mais principalement de la viande !'); end; |
La directive override définit une méthode de classe comme surchargeant la même méthode nommée dans une classe parente. L'ancienne méthode est toujours accessible grâce à inherited.
Code pascal : | Sélectionner tout |
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 | type TMyClass = class procedure MyProc; virtual; end; TMySubClass = class(TMyClass) procedure MyProc; override; end; [...] implementation procedure TMyClass.MyProc; begin Width := 50; Height := 60; end; procedure TMySubClass.MyProc; begin inherited; // on reprend ce que fait la méthode de l'ancêtre Top := 100; // nouvelle valeur end; |
N.B. : la directive override ne s'applique qu'à des méthodes virtuelles.
Avec Free Pascal, une méthode marquée dynamic n'est rien d'autre qu'une méthode virtuelle. dynamic est par conséquent équivalent à virtual.
La directive dynamic existe pour la compatibilité avec Delphi.
La directive reintroduce signifie au compilateur que l'écrasement de la méthode virtuelle de l'ancêtre est volontaire.
Redéfinir complètement une méthode virtuelle par une méthode statique provoque un avertissement du compilateur : faire suivre la redéfinition de la méthode virtuelle par la directive reintroduce évite cet avertissement.
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 7 8 | // méthode du parent TMyClass = class procedure MyProc; // la méthode est virtuelle end; // méthode du descendant TMySubClass = class(TMyClass) procedure MyProc; reintroduce; // la méthode virtuelle est écrasée |
N.B. : Cette directive est utile pour surcharger une méthode dont il faut modifier les paramètres d'appel, par exemple pour un constructeur.
Une méthode abstraite est un squelette de méthode déclarée dans une classe, mais non implémentée. Ce sont les descendants de la classe où la déclaration a eu lieu qui l'implémenteront en temps voulu.
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | type TMyClass = class public procedure DoSomething; virtual; abstract; end; TMySubClass = class(TMyClass) public procedure DoSomething; override; end; |
N.B. : Une méthode abstraite doit toujours être déclarée virtuelle. Faute d’implémentation, on prendra bien garde de ne pas faire appel à ces méthodes et de ne pas utiliser inherited lors d’un héritage direct.
L'intérêt de la directive abstract est d'unifier les déclarations et le comportement des classes tout en bénéficiant totalement du polymorphisme si nécessaire.
Par exemple, les descendants de TStrings procéderont à l'implémentation de ses méthodes abstraites tandis qu'en tant qu’ancêtre, TStrings sera d’une grande polyvalence puisque n'importe quel descendant pourra prendre sa forme.
Comparez :
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 7 | procedure Afficher(Sts: TStringList); var LItem: string; // variable locale pour récupérer les chaînes une à une begin for LItem in Sts do // on balaie la liste writeln(LItem); // et on affiche l’élément en cours end; |
Et :
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 7 | procedure Afficher(Sts: TStrings); // <= seul changement var LItem: string; begin for LItem in Sts do writeln(LItem); end; |
La première procédure n'acceptera pour paramètre que les objets de type TStringList. La seconde acceptera tous les descendants de TStrings, y compris TStringList, se montrant par conséquent bien plus polyvalente.
Avec les méthodes de classe, vous ne vous intéresserez plus à l’instanciation, mais à la manipulation directe de la classe. Dans d’autres domaines, on parlerait de métadonnées. Il est par conséquent inutile d’instancier une classe pour accéder à ces méthodes particulières, même si cela reste possible.
La déclaration d’une méthode de classe se fait en plaçant le mot-clé class avant de préciser s’il s’agit d’une procédure ou d’une fonction.
Par exemple, voici comment déclarer une fonction qui renverrait le copyright associé à un programme :
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 | type TMyClass = class public class function Copyright: string; end; |
L'implémentation doit reprendre class et pourrait ressembler à :
Code pascal : | Sélectionner tout |
1 2 3 4 | class function TMyClass.Copyright: string; begin Result := 'www.developpez.com 2016'; end; |
Pour qu'une étiquette affiche le texte du copyright, l'appel prendrait alors la forme :
Code pascal : | Sélectionner tout |
MyLabel.Caption := TMyClass.Copyright;
L’important est de remarquer que l’appel a été effectué sans instancier TMyClass.
En ajoutant la directive static à la fin de la déclaration d’une méthode de classe, vous obtenez une méthode statique de classe.
Une méthode statique de classe ne connaît ni le paramètre Self ni la virtualité. En fait, une méthode de ce type se comporte en tout point comme procédure ou fonction ordinaires.
Code pascal : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | type TMyClass = class private class var fMyValue: string; protected class procedure SetMyValue(const AValue: string); static; class function GetMyValue: string; static; public class property MyValue: string read GetMyValue write SetMyValue; end; |
L'utilisation d'une méthode statique de classe au lieu d'une routine globale permet de la nommer avec le préfixe de la classe et non celui de l’unité où elle a été définie : c'est là son principal usage. Grâce à ce changement d'espace de nommage, la lisibilité du code en est meilleure et les conflits de noms en sont d'autant limités.
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.