Programmation, langages, compilation 2 (TD/TP) Programmation modulaire et orientée objets E. Lozes Corrigé de l exercice 1 1. Commençons par le cas de Caml. ( i n t e r f a c e du compteur en CAML ) module type COMPTEUR = s i g i n c r : unit > unit e v a l : unit > i n t r e s e t : unit >unit ( i m p l a n t a t i o n du compteur en CAML ) ( é v e n t u e l l e m e n t dans des f i c h i e r s s é p a r é s ) ( compteur. ml pour l i m p l a n t a t i o n ) ( e t compteur. mli pour l i n t e r f a c e ) module Compteur : COMPTEUR = struct l e t cnt = ref ( 0 ) ( < donnée p r i v é e, pas dans l e s i g ) l e t i n c r ( ) = cnt :=! cnt +1 l e t e v a l ( ) =! cnt l e t r e s e t ( ) = cnt := 0 ( un a ppel au module ) ( e v e n t u e l l e m e n t dans un autre f i c h i e r ) Compteur. r e s e t ( ) En C, voilà comment on ferait : // i n t e r f a c e du compteur // f i c h i e r compteur. h extern void i n c r ( ) ; extern int e v a l ( ) ; 1
extern void r e s e t ( ) ; // i m p l a n t a t i o n du compteur // f i c h i e r compteur. c static int cnt = 0 ; void i n c r ( ) { cnt++ int e v a l ( ) { return cnt void r e s e t ( ) { cnt = 0 // un appel dans un autre f i c h i e r // charger l e s d é c l a r a t i o n s de f o n c t i o n s #include compteur. h [.. ] r e s e t ( ) ; //un appel On peut donc noter que l appel externe en Caml se fait avec l identificateur de l implantation (qui doit être aussi le nom du fichier), tandis qu en C elle se fait en se basant sur une déclaration de fonction externe insérée dans chaque fichier appelant. C permet donc de choisir plus tard quelle sera vraiment l implantation de la fonction que l on voudra utiliser. En Caml, si on veut appeler une fonction dont on a seulement une interface (et qu on souhaite le faire avec plusieurs implantations possibles), il faudra utiliser un foncteur (voir plus loin). 2. La compilation séparée consiste à compiler un module sans savoir explicitement le code de toutes fonctions qui peuvent être appellées, certaines étant définies dans d autres modules. Lédition de lien est l étape finale de la compilation : on regroupe en un seul fichier (l exécutable) le code de tous les modules et on met à jour l adresse de chaque fonction appellée. L intérêt de ce procédé est multiple, on peut au moins citer comme avantages d un code compartimenté : clarté du code : aide à la conception et au déverminage du code possibilité d un développement en équipe réutilisation de certains modules pour d autres codes pour des modules très utilisés : chargement en mémoire d une seule copie, liée dynamiquement (les librairies, ex : DLL sous windows) 3. Pour faire la même chose que le module compteur précédent, on peut écrire en Caml : l e t compteur = l e t cnt = ref ( 0 ) in { i n c r = fun ( ) > cnt := cnt+1 e v a l = fun ( ) >! cnt r e s e t = fun () > cnt := 0 2
[.. ] compteur. r e s e t ( ) 4. Avec un objet, on ferait : class compteur = object val mutable cnt = 0 method i n c r = cnt< cnt+1 method e v a l = cnt method r e s e t = cnt< 0 l e t compteur1 = new compteur compteur#r e s e t La principale différence avec un module est que l on peut créer dynamiquement plusieurs objets instances d une même classe, alors qu un module n admet qu une seule instance. 5. Pour pouvoir créer des modules qui permettent de manipuler plusieurs instances de compteurs, une solution est de définir un type abstrait compteur, et rajouter un compteur en argument aux fonctions incr, eval, reset, et rajouter dans l interface une fonction de création newcompteur. On utilise une référence globale non définie dans l interface pour stocker un numero de version frais pour le prochain compteur, ou mieux une variable locale statique dans la fonction new. En objet, il n y a aucun problème pour avoir plusieurs instances de compteurs, le problème vient du numéro de version ; une solution est d utiliser en Java un champ statique, c est à dire un champs qui sera commun à tous les objets Corrigé de l exercice 2 On considère le code Java suivant : String nom; Personne(String nom){this.nom=nom String nomme () {return this.nom class Monde{ void salut(personne p){system.out.println("bonjour "+ p.nomme()); Monde(){ Personne toto = new Personne("toto"); this.salut(toto); 1. Sur cet exemple, qu est-ce qu une classe, un objet, une méthode, un champ, un constructeur? Si on rajoute une personne, comment fait-on? Qu est-ce 3
qui sera partagé entre eux? Quel est le but général des mots public, private, protected placés devant une déclaration de champ? 2. On veut ajouter des personnes pour lesquelles on aura davantage d informations. Pour cela, on définit une classe descant de la classe Personne : class Personne2 exts Personne { Personne2(String nom, String prenom){ super(nom); this.prenom = prenom; String nomme() {return this.nom+" "+this.prenom et on rajoute au monde Jeannot Lapin. Comment va-t-on le saluer? Que penser du type des objets de classes descantes? 3. On ajoute une méthode Presentation à la classe Personne : [..] void presentation(){system.out.println("bonjour, je m appelle"+this.nomme()); On demande à chacun de se présenter dans le monde. Que se passe-til? Quel type de liaison est mis en oeuvre? Quelles sont les méthodes masquées dans la sous-classe? 4. On ajoute maintenant une méthode presentation(personne p) à côté de la première dans la classe Personne : [..] void presentation(){system.out.println("bonjour, je m appelle"+this.nomme()); void presentation(personne p){ System.out.println("Bonjour,"+ p.nomme()+", je m appelle"+this.nomme()); C est le polymorphisme par surcharge : le type des arguments permet au compilateur de trouver à quelle méthode il est fait référence. Comment voit-t-on ces choses en CAML? 5. Que se passe-t-il si Jeannot Lapin se présente à toto? Redéfinissez presentation dans Personne2 de façon à obtenir Bonjour toto, je m appelle Lapin. 6. Qu est-ce qu une classe abstraite? Donnez un exemple. 7. Qu est-ce qu une interface? Pourquoi cela existe-t-il alors qu il y a des classes abstraites? 8. Cherchez le sens des mot-clés suivants : public, private, protected, final, et static. Corrigé de l exercice 3 4
1. tototo 5