Section courante

A propos

Section administrative du site

Quick Pascal et Turbo Pascal 5.5 - des compilateurs Pascal rapides et conviviaux avec des extensions orientées objet

Les produits Pascal de 1989 de Microsoft et de Borland ont pris les développeurs par surprise. Les deux commencent là où Turbo Pascal s'est arrêté pour créer un véritable langage orienté objet.

Le Quick Pascal de Microsoft (100 $ USD en 1989), dont la livraison fut en mai 1989, suit de près l'Object Pascal d'Apple. Le Turbo Pascal 5.5 de Borland (150 $ USD en 1989), également prévu pour mai 1989, s'appuie également sur Object Pascal, mais il ajoute quelques idées de C++ et quelques fonctionnalités originales.

Pourquoi la surprise ? Eh bien, tous le monde s'attendait que les premiers produits POO (programmation orientée objet) des géants du langage testeraient les eaux C++ dans lesquelles d'autres fournisseurs, tels que Zortech, se sont aventurés. Les projets C++ sont encore à se moment sur les planches à dessin chez Microsoft et Borland, mais, les Pascals sont de beaux environnements dans lesquels explorer la POO. Il semble approprié que Pascal, le langage ayant enseigné à une génération de programmeurs la programmation structurée, puisse sous une nouvelle forme enseigner à une autre génération la POO.

Un véritable langage orienté objet doit prendre en charge à la fois l'encapsulation et l'héritage. L'encapsulation signifie que le langage fournit un moyen de combiner les données et le code opérant sur ces données dans des structures réutilisables. Mais cela ne suffit pas. Bien que les paquets d'Ada et les modules de Modula-2 prennent en charge l'encapsulation, ce ne sont pas des langages orientés objet au sens moderne du terme. L'héritage, étant la capacité de dériver une structure spécialisée d'une structure plus générale, est l'ingrédient crucial.

Comme Object Pascal, Quick Pascal et Turbo Pascal 5.5 implémentent l'héritage au moyen d'un nouveau type Pascal appelé objet. Comme un enregistrement Pascal, un objet peut contenir des données de différents types. Mais un objet peut également contenir des méthodes (procédures ou fonctions Pascal) opérant sur les données de l'objet. De plus, un objet peut hériter des données et des méthodes d'un autre objet, ajouter de nouvelles données et méthodes et (si nécessaire) remplacer les méthodes héritées.

Bien que des différences subtiles existent entre les dialectes orientés objet que les deux produits implémentent, ils sont comparables en portée et en puissance. Ils n'offrent pas la généralité et l'intégralité conceptuelle d'un langage orienté objet pur comme Smalltalk, dans lequel tout est soit un objet, soit un message. Mais ce ne sont en aucun cas des langages jouets. Les avantages des extensions orientées objet seront immédiats et tangibles.

Considérez une famille d'objets définissant des fichiers de différents types et des opérations sur les fichiers. Un objet racine, File, peut définir des données (Position, Length, CreateDate) et des méthodes (GetByte, PutByte, SetCreateDate) communes à tous les fichiers. Les objets dérivés MagDiskFile et NetworkFile peuvent alors hériter des données de File mais redéfinir ses méthodes d'une manière appropriée au support utilisé.

Supposons maintenant que tous ces objets soient compilés (en utilisant Quick Pascal ou Turbo Pascal 5.5) et distribués comme une unité standard appelée Files. Supposons en outre que vous achetiez l'unité Files et que vous souhaitiez ajouter la prise en charge d'un nouveau type de fichier, un OpticalDiskFile. Vous pouvez, sans accéder au code source de l'unité Files, acquérir ses données et ses méthodes, définir l'objet OpticalDiskFile et implémenter le nouvel objet avec un minimum d'effort en remplaçant uniquement les méthodes concernées par les caractéristiques spécifiques d'un lecteur optique.

Un tel système a deux propriétés remarquables. Tout d'abord, vous n'avez pas besoin d'écrire de code pour implémenter SetCreateDate. Étant donné que SetCreateDate se préoccupe d'une propriété abstraite de File, il n'est pas nécessaire de modifier la méthode SetCreateDate de File. OpticalDiskFile peut simplement en hériter. Deuxièmement, bien que vous deviez écrire une nouvelle implémentation de GetByte et PutByte, étant donné que ces méthodes communiquent avec un périphérique physique, vous n'auriez pas à modifier les programmes qui utilisent l'interface avec l'unité File. Les programmes appelant GetByte et PutByte peuvent continuer à le faire, ignorant parfaitement qu'ils pourraient maintenant parler à un lecteur optique plutôt qu'à un disque magnétique ou à un canal réseau.

Quick Pascal : Turbo Pascal avec des objets

Si vous êtes familier avec Turbo Pascal, vous ressentirez une sensation de déjà-vu lorsque vous lancerez l'environnement intégré de Quick Pascal. Les deux produits ont une apparence et une sensation étonnamment similaires. Un éditeur de texte domine l'environnement ; à partir de là, vous accédez au compilateur et au débogueur. Lorsque vous éditez du code source Pascal, l'aide est contextuelle. Si le curseur est sur le mot Crt - le nom de la bibliothèque de routines utilitaires - la touche d'aide affiche la liste des routines de cette bibliothèque.

Lorsque vous activez le compilateur et qu'il rencontre une erreur, Quick Pascal place le curseur au bon endroit pour la corriger. Si le fichier courant fait référence à d'autres unités (l'équivalent Turbo Pascal des paquets ou des modules), vous pouvez compiler transitivement l'ensemble du réseau d'unités. Une fois qu'un programme se compile proprement, vous pouvez soit l'exécuter, soit le déboguer. Avec le débogueur, vous pouvez parcourir le code source ligne par ligne et voir les valeurs des variables sélectionnées dans une fenêtre de surveillance.

Comme Turbo Pascal, Quick Pascal permet d'échapper à l'étreinte parfois écrasante de son environnement intégré sous la forme d'une version en ligne de commande du compilateur. C'est une chance pour moi car je suis beaucoup plus productif avec mon propre éditeur de texte et un compilateur autonome qu'avec n'importe lequel des environnements intégrés que j'ai vus. Les versions en ligne de commande de Turbo Pascal 5.5 et Quick Pascal offrent un ensemble pratiquement identique de commutateurs pour contrôler la vérification de la pile, les informations de débogage et l'arithmétique en virgule flottante. Cependant, le Quick Pascal ne fournit pas de débogueur autonome (comme le fait Turbo Pascal), donc si vous voulez déboguer un programme, vous devez utiliser l'environnement intégré. Le Quick Pascal prend en charge les mots-clefs unité, interface, implémentation et utilisations. Cette syntaxe, introduite par Borland avec Turbo Pascal 4.0, encourage la construction et l'utilisation de bibliothèques (unités) exportant les définitions de routines utiles (l'interface) vers tout programme qui acquiert (utilise) ces bibliothèques, tout en cachant les détails du code (la mise en oeuvre). Le Quick Pascal propose la plupart des unités standard de Turbo Pascal : Crt (routines d'écran et de clavier), Dos, Printer et Graph.

Bien qu'il existe également une unité MSGraph fournissant une interface alternative aux routines graphiques, l'unité Graph de Quick Pascal est essentiellement le BGI (Borland Graphic Interface). Et bien sûr, Quick Pascal a compilé et exécuté la démo graphique de Borland, BGIDEMO.PAS, presque parfaitement. Microsoft a clairement lancé un assaut frontal sur le produit phare de Borland.

Le comportement de type Windows de Quick Pascal soulage le sentiment de similitude. Contrairement à Turbo Pascal, le Quick Pascal, bien que basé sur des caractères, présente des fenêtres sportives avec des barres de glissement, des barres de défilement, des boîtes de croissance et des boîtes de fermeture sensibles à la souris. A une résolution de 80 colonnes sur 25 lignes, l'effet visuel est moins spectaculaire, mais le mécanisme peut néanmoins être utile. Si vous n'avez pas de souris, vous pouvez bien sûr tout faire avec le clavier ; le programme prend en charge les conventions normales de Microsoft Windows.

Turbo Pascal 5.5 : la nouvelle génération

Si on la compare avec une version plus ancienne comme une copie de Turbo Pascal 2.0 datant de 1985, les changements sont impressionnants. Au fil des ans, Turbo Pascal a acquis un certain nombre de fonctionnalités importantes : des unités compilées séparément, une boîte à outils graphique, une interface multifenêtre et un débogueur extrêmement puissant. Borland a maintenant ajouté des extensions orientées objet étant assez similaires à celles proposées par Microsoft mais à plusieurs égards plus utiles.

L'implémentation OOP de Borland englobe celle de Microsoft et ajoute des méthodes statiques, une allocation dynamique plus flexible des objets et un accès implicite aux données et méthodes des objets. Chacune de ces caractéristiques prend un peu d'explication.

Des méthodes telles que GetByte et PutByte de l'unité Files illustrent ce qu'on appelle une liaison tardive. Lorsque l'unité compile, les adresses de ces routines ne peuvent pas être connues car, comme je l'ai expliqué dans le cas d'OpticalDiskFile, le code n'existe peut-être pas encore. Dans Turbo Pascal 5.5, vous déclarez de telles méthodes avec le mot-clef spécial virtual ; un appel à une méthode virtuelle se lie tardivement, c'est-à-dire au moment de l'exécution. Vous avez vu la flexibilité que cette technique confère. Il y a aussi des coûts. Les objets doivent entreposer des pointeurs vers leurs méthodes, et le système d'exécution doit utiliser ces pointeurs pour localiser et exécuter des méthodes. De plus, toutes les méthodes virtuelles partageant le même nom (par exemple, File.GetByte, Network.GetByte et OpticalDiskFile.GetByte) doivent déclarer le même nombre et les mêmes types de paramètres.

Dans Quick Pascal, toutes les méthodes sont virtuelles ; il n'y a pas d'autre alternative. Dans Turbo Pascal 5.5, les méthodes sont statiques ou à liaison anticipée, à moins que vous ne demandiez spécifiquement le contraire. Parce qu'elles sont intégrées dans des objets, les méthodes statiques devraient être un peu plus lentes que les procédures et fonctions Pascal normales, mais comme leurs adresses sont connues au moment de la compilation, elles devraient être un peu plus rapides que les méthodes virtuelles. En fait, c'est exactement ce que l'on trouve lorsque j'ai chronométré 1 million d'appels de procédure Turbo Pascal 5.5 (4,1 secondes), d'appels de méthode statique (5,7 secondes) et d'appels de méthode virtuelle (6,1 secondes). Les temps équivalents pour Quick Pascal étaient les suivants : procédures, 4,1 secondes ; méthodes statiques, sans objet ; méthodes virtuelles, 6,7 secondes.

Bien que les méthodes statiques de Turbo Pascal 5.5 soient plus efficaces que les méthodes virtuelles, elles ne le sont pas de manière écrasante et la vitesse n'est pas une raison impérieuse de les utiliser, la commodité l'est. Supposons que l'objet File ait une méthode Initialize. Les objets que vous dérivez de File peuvent nécessiter différentes quantités et types de données pour s'initialiser. Par exemple, dans un cas, vous voudrez peut-être appeler :

  1. MagDiskFile.Initialize(name,bufsize)

et dans un autre cas :

  1. OpticalDiskFile.Initialize(name,buf1size, buf1address,buf2size, buf2address)

Les méthodes statiques de Turbo Pascal 5.5 le permettent.

Différences subtiles

Dans Quick Pascal, les objets se comportent comme des variables dynamiques. Pour obtenir une instance de MagDiskFile, vous déclarez d'abord une variable de ce type, puis appelez New pour lui allouer de l'espace :

  1. Var
  2.  MyFile:MagDiskFile;
  3. Begin
  4.  New(MyFile);

Dans Turbo Pascal 5.5, les objets se comportent comme des variables statiques. Pour créer une instance de MagDiskFile, il vous suffit de faire ceci :

  1. Var
  2.  MyFile:MagDiskFile;

Vous pouvez également choisir d'allouer une instance dynamiquement, en utilisant la syntaxe de pointeur normale de Pascal :

  1. Var
  2.  MyFilePtr:^MagDiskFile;
  3. Begin
  4.  New(MyFilePtr);

De plus, Borland a étendu la syntaxe de New afin qu'il fonctionne avec un autre mot clef, Constructor. Les constructeurs (et leurs homologues, les destructeurs) viennent du C++. Dans ce langage, vous pouvez écrire du code s'exécutant automatiquement au début et à la fin de la durée de vie d'un objet. Un objet nécessite généralement une mémoire dynamique pour remplir sa mission; Les constructeurs et les destructeurs sont des emplacements pratiques pour localiser l'allocation et la libération de cette mémoire.

Les extensions de Turbo Pascal 5.5 à New sont triples : vous pouvez passer à New un type de pointeur plutôt qu'une variable de pointeur; vous pouvez passer un deuxième paramètre facultatif étant un constructeur; et vous pouvez renvoyer la valeur du pointeur que New crée :

  1. Type 
  2.  MagDiskFilePtr=^MagDiskFile;
  3.  
  4. Var 
  5.  MyFilePtr:MagDiskFilePtr;
  6. Begin
  7.  MyFilePtr:=New(MagDiskFilePtr, Initialize('mafiche',1024));

Les opérations équivalentes en Quick Pascal sont les suivantes :

  1. Var 
  2.  MyFile:MagDiskFile;
  3. Begin
  4.  New(MyFile);
  5.  MyFile.Initialize('mafiche',1024);

Quel est donc le gros avantage ? Dans ce cas, il n'y en a pas. Mais considérez ce qui se passe lorsque vous souhaitez manipuler plusieurs objets de type MagDiskFile. Dans Turbo Pascal 5.5, MyFilePtr ne fait référence à un objet qu'indirectement. L'objet vers lequel il pointe est anonyme. Par conséquent, vous pouvez dynamiquement allouer et initialiser une liste d'instances d'objet comme celle-ci :

  1. Var
  2.  i:Integer;
  3.  
  4. Begin
  5.  For i:=1 to FileCount do FileList.Add(New(MyFilePtr, Initialize(FileName[i],1024)));

FileList est un objet prenant un pointeur vers un objet de type File (ou vers l'un des descendants de File) et l'ajoute à une liste de ces pointeurs.

Dans Quick Pascal, cependant, MyFile fait directement référence à un objet. Pour créer et initialiser trois instances, vous devez procéder comme suit :

  1. Var
  2.  MyFile1,MyFile2,MyFile3:MagDiskFile;
  3. Begin
  4.  New(MyFile1);
  5.  New(MyFile2);
  6.  New(MyFile3);
  7.  MyFilel.Initialize('myfile1',1024);
  8.  MyFile2.Initialize('myfile2',1024);
  9.  MyFile3.Initialize('myfile3',1024);

Turbo Pascal 5.5 fournit également une extension parallèle à disposer. Vous pouvez passer dispose d'un destructeur, ainsi, en un seul appel, vous pouvez activer la méthode d'arrêt d'un objet, puis libérer sa mémoire.

Une autre commodité offerte par Turbo Pascal 5.5 concerne la façon dont un objet accède à ses propres données. Voici à quoi ressemblerait Initialize dans Quick Pascal :

  1. Procedure Initialize(InitName:String;InitBufsize:Integer);Begin
  2.  Self.Name:=InitName;
  3.  Self.Bufsize:=InitBufsize;
  4.  Self.SetCreateDate;
  5. End;

Initialize affecte des valeurs aux emplacements Name et Bufsize de l'objet et appelle sa méthode SetCreateDate. Mais pour y accéder, Initialize, même s'il appartient déjà à l'objet, doit tout qualifier avec Self - affirmant simplement «oui, allez-y et opérez sur cet objet». Turbo Pascal 5.5 rend Self implicite, donc la méthode équivalente est simplement :

  1. Procedure Initialize(InitName:String;InitBufsize:Integer);Begin
  2.  Name:=InitName;
  3.  Bufsize:=InitBufsize;
  4.  SetCreateDate;
  5. End;

C'est une petite chose, mais une fois que vous avez passé du temps avec Turbo Pascal 5.5, c'est ennuyeux de passer à Quick Pascal et de devoir taper "Self" constamment.

Choisissez votre POO

La sortie de ces deux excellents produits a fait beaucoup pour faire avancer la cause du POO. Je recommanderais l'un ou l'autre à C++ pour une introduction à ce qui est à bien des égards un sujet déconcertant. Mais lequel ? Pour moi, ce n'est pas un concours : je choisirais le Turbo Pascal 5.5 de Borland.

Les points en faveur de Quick Pascal incluent une excellente vitesse, des graphismes parfois meilleure, un environnement de type Windows, un débogueur intégré, une aide en ligne et des extensions orientées objet. Parmi ceux-ci, les seules fonctionnalités unique à Quick Pascal est l'environnement de type Windows et la gestion du mode d'affichage 320x200 en 256 couleurs intégré à MSGraph. Cela ne pèse pas lourd pour les développeurs d'application de gestion.

Le Turbo Pascal 5.5 correspond ou améliore Quick Pascal à tous autres égards. C'est plus rapide - même si vous aurez besoin d'un très gros programme avant que l'un ou l'autre de ces produits ne vous fasse attendre longtemps. Son aide en ligne est mieux organisée. Là où Quick Pascal affiche simplement la partie interface de, par exemple, l'unité Crt, le Turbo Pascal 5.5 vous donne une liste de noms de routines dans cette unité. Lorsque vous sélectionnez un nom, vous obtenez un autre écran avec l'entête de la procédure et la documentation descriptive.

Bien que les deux débogueurs intégrés se correspondent fonctionnalité par fonctionnalité, Turbo Pascal 5.5 est également livré avec le débogueur autonome renommé de Borland. Contrairement à l'un ou l'autre des débogueurs intégrés, le débogueur turbo peut tracer un mélange de code source et d'assemblage et peut inspecter des variables complexes (par exemple, décompresser des enregistrements imbriqués et suivre des chaînes de pointeurs). Borland a maintenant ajouté une nouvelle fonctionnalité liée à la POO : un inspecteur de hiérarchie d'objets. Cet outil affiche et parcourt une famille d'objets. Il peut inspecter les données appartenant à un objet et identifier les méthodes de l'objet. C'est très impressionnant et donne à Turbo Pascal 5.5 la sensation d'un système Smalltalk.

Enfin, bien que les deux dialectes POO soient à peu près équivalents, celui de Borland englobe celui de Microsoft et ajoute plusieurs commodités assez utiles. La bataille est malheureusement terminée et Microsoft ne proposa de version de Quick Pascal par la suite. Toutefois, la technologie orientée objet à pris de plus en plus de place et apparu ensuite sous d'autres formes. Il y a peu d'espoir de maîtriser les complexités des environnements graphiques modernes sans l'effet de levier fourni par POO.



Dernière mise à jour : Jeudi, le 20 janvier 2022