MODULE TransportsAbstrait; Véhicule = POINTER TO ABSTRACT RECORD prix: REAL; nbpassmax: INTEGER ChoseTransportée =POINTER TO ABSTRACT RECORD poids: REAL; ident: ARRAY 81 OF CHAR PROCEDURE (v: Véhicule) Coût (nbpass: INTEGER; dist: REAL): REAL, NEW, ABSTRACT; PROCEDURE (v: Véhicule) ToString (): POINTER TO ARRAY OF CHAR, NEW, ABSTRACT; PROCEDURE (c: ChoseTransportée) ToString (): POINTER TO ARRAY OF CHAR, NEW, ABSTRACT; END TransportsAbstrait. Rappel: Un est la définition d'une entité regroupant des caractéristiques communes. Une classe est un où les caractéristiques regroupées sont les données et les traitements Une classe abstraite c'est la définition d'une pure forme dont on ne pourra créer d'instances. On devra, pour l'employer, créer des classes dérivées concrètes. La classe abstraite est obtenue à l'issue de l'analyse par factorisation de caractéristiques communes. / Véhicule.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / public abstract class Véhicule { public double prix; public int nbpassmax; public abstract double coût (int nbpass, double dist); public abstract String tostring (); } // Véhicule / ChoseTransportée.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / public abstract class ChoseTransportée { public double poids; public String ident; public abstract String tostring (); } // ChoseTransportée Remarques: Un module peut encapsuler plusieurs classes. Ici, il y en a 2. Deux classes différentes peuvent avoir des méthodes de même nom (ici ToString). Tout comme deux champs données de deux RECORDs différents peuvent avoir le même nom.
MODULE TransportsConcret; TransportsAbstrait, ZStrPlus; Voiture = POINTER TO EXTENSIBLE RECORD (TransportsAbstrait.Véhicule) nbportes: INTEGER Moto = POINTER TO EXTENSIBLE RECORD (TransportsAbstrait.Véhicule) sélecteurgauche: BOOLEAN Passager = POINTER TO RECORD (TransportsAbstrait.ChoseTransportée) classe: INTEGER ( 1e, 2e ou 3e classe ) Fret = POINTER TO RECORD (TransportsAbstrait.ChoseTransportée) prix: REAL PROCEDURE (v: Voiture) Coût (nbpass: INTEGER; dist: REAL): REAL, EXTENSIBLE; BEGIN (Coût) RETURN 10distnbPass; ( Pourrait être affiné, ce n'est pas le but ici. ) PROCEDURE (v: Voiture) ToString (): POINTER TO ARRAY OF CHAR, EXTENSIBLE ; BEGIN (ToString) RETURN ZStrPlus.DynStr("Voiture") PROCEDURE (m: Moto) Coût (nbpass: INTEGER; dist: REAL): REAL, EXTENSIBLE; BEGIN (Coût) RETURN 4distnbPass; PROCEDURE (m: Moto) ToString (): POINTER TO ARRAY OF CHAR, EXTENSIBLE; BEGIN (ToString) RETURN ZStrPlus.DynStr("Moto") PROCEDURE (p: Passager) ToString (): POINTER TO ARRAY OF CHAR; BEGIN (ToString) RETURN ZStrPlus.DynStr(p.ident) ( L'identificateur p désigne l'instance courante. ) PROCEDURE (f: Fret) ToString (): POINTER TO ARRAY OF CHAR; BEGIN (ToString) RETURN ZStrPlus.DynStr(f.ident) ( L'identificateur f désigne l'instance courante. ) END TransportsConcret. On doit implanter explicitement toutes les méthodes ABSTRACT héritées de la classe mère. / Voiture.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / public class Voiture extends Véhicule { public int nbportes; return 10 dist nbpass; // Pourrait être affiné, ce n'est pas le but ici return "Voiture"; } // Voiture / Moto.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / public class Moto extends Véhicule { public boolean sélecteurgauche; return 4 dist nbpass; return "Moto"; } // Moto / Passager.java @author Peter DAEHNE, 04.10.2006 @version 0.1 / public final class Passager extends ChoseTransportée { public int classe; // 1e, 2e ou 3e classe return this.ident; // Le this n'est ici pas nécessaire (sinon on préfixerait tout par this) } // Passager / Fret.java @author Peter DAEHNE, 04.10.2006 @version 0.1 / public final class Fret extends ChoseTransportée { public double prix; return this.ident; // Le this n'est ici pas nécessaire (sinon on préfixerait tout par this) } // Fret
MODULE TransportsConcretExt; TransportsConcret, ZStrPlus; QuatreQuatre = POINTER TO EXTENSIBLE RECORD (TransportsConcret.Voiture) MonoSpace = POINTER TO EXTENSIBLE RECORD (TransportsConcret.Voiture) SideCar = POINTER TO EXTENSIBLE RECORD (TransportsConcret.Moto) / QuatreQuatre.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / public class QuatreQuatre extends Voiture { public final void autreméthode () { } // autreméthode return 15 dist nbpass; return "4x4"; } // QuatreQuatre PROCEDURE (q: QuatreQuatre) AutreMéthode (), NEW ; BEGIN (AutreMéthode) END AutreMéthode; PROCEDURE (q: QuatreQuatre) Coût (nbpass: INTEGER; dist: REAL): REAL, EXTENSIBLE; BEGIN (Coût) RETURN 15distnbPass; PROCEDURE (q: QuatreQuatre) ToString (): POINTER TO ARRAY OF CHAR, EXTENSIBLE; BEGIN (ToString) RETURN ZStrPlus.DynStr("4x4") PROCEDURE (m: MonoSpace) Coût (nbpass: INTEGER; dist: REAL): REAL, EXTENSIBLE; BEGIN (Coût) RETURN 11distnbPass; PROCEDURE (m: MonoSpace) ToString (): POINTER TO ARRAY OF CHAR, EXTENSIBLE; BEGIN (ToString) RETURN ZStrPlus.DynStr("Monospace") PROCEDURE (s: SideCar) Coût (nbpass: INTEGER; dist: REAL): REAL, EXTENSIBLE; BEGIN (Coût) RETURN 4distnbPass; PROCEDURE (s: SideCar) ToString (): POINTER TO ARRAY OF CHAR, EXTENSIBLE; BEGIN (ToString) RETURN ZStrPlus.DynStr("SideCar") / MonoSpace.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / public class MonoSpace extends Voiture { return 11 dist nbpass; return "Monospace"; } // MonoSpace / SideCar.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / public class SideCar extends Moto { return 4 dist nbpass; return "SideCar"; } // SideCar END TransportsConcretExt.
MODULE TransportsConcretExtExt; TransportsConcretExt, ZStrPlus; SUV = POINTER TO EXTENSIBLE RECORD (TransportsConcretExt.QuatreQuatre) PROCEDURE (s: SUV) Coût (nbpass: INTEGER; dist: REAL): REAL, EXTENSIBLE; BEGIN (Coût) RETURN 21distnbPass; / SUV.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / public class SUV extends QuatreQuatre { return 21 dist nbpass; return "SUV"; } // SUV PROCEDURE (s: SUV) ToString (): POINTER TO ARRAY OF CHAR, EXTENSIBLE; BEGIN (ToString) RETURN ZStrPlus.DynStr("SUV") END TransportsConcretExtExt.
MODULE TransportsClient0; Out, TransportsAbstrait, TransportsConcret; PROCEDURE Do; pass: TransportsConcret.Passager; fret: TransportsConcret.Fret; véh: TransportsAbstrait.Véhicule; ( Il est possible de déclarer une référence à un type abstrait. ) chose: TransportsAbstrait.ChoseTransportée; ( Ditto. ) BEGIN (Do) ( Méditer l'erreur déclenchée par le verso de ce Fold. ) Out.Ln; Out.String("Le véhicule voit est de type "+voit.tostring()); Out.Ln; Out.String("Le véhicule moto est de type "+moto.tostring()); NEW(pass); NEW(fret); ( Méditer l'erreur déclenchée par le verso de ce Fold. ) pass.ident := "Charles-Henry";( Attention: chapeau rose!!!! ) fret.ident := "valises"; Out.Ln; Out.String("Le passager est "+pass.tostring()); Out.Ln; Out.String("Le fret est "+fret.tostring()); END TransportsClient0.! TransportsClient0.Do Erreur: L'erreur est bien sûr qu'on ne peut pas allouer des types ABSTRACTs. Le POINTER lui peut être alloué automatiquement (la déclaration locale), ce qu'on ne peut pas faire, c'est allouer la zone pointée. MODULE TransportsClient0; Out, TransportsAbstrait, TransportsConcret; PROCEDURE Do; pass: TransportsConcret.Passager; fret: TransportsConcret.Fret; véh: TransportsAbstrait.Véhicule; ( Il est possible de déclarer une référence à un type abstrait. ) chose: TransportsAbstrait.ChoseTransportée; ( Ditto. ) BEGIN (Do) NEW(véh); ( Méditer l'erreur déclenchée. ) Out.Ln; Out.String("Le véhicule voit est de type "+voit.tostring()); Out.Ln; Out.String("Le véhicule moto est de type "+moto.tostring()); NEW(pass); NEW(fret); NEW(chose); ( Méditer l'erreur déclenchée. ) pass.ident := "Charles-Henry";( Attention: chapeau rose!!!! ) fret.ident := "valises"; Out.Ln; Out.String("Le passager est "+pass.tostring()); Out.Ln; Out.String("Le fret est "+fret.tostring()); / Client0.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / import transports.; public class Client0 { / Traduction avec les déclarations de variable groupées au début de la méthode, comme en Pascal / public static void main0 (String[] args) { Voiture voit; Moto moto; Passager pass; Fret fret; Véhicule véh; ChoseTransportée chose; voit = new Voiture(); moto = new Moto(); //véh = new Véhicule(); // Méditer l'erreur déclenchée par cette instruction System.out.println(); System.out.println("Le véhicule voit est de type " + voit.tostring()); System.out.println("Le véhicule moto est de type " + moto.tostring()); pass = new Passager(); fret = new Fret(); //chose = new ChoseTransportée(); // Méditer l'erreur déclenchée par cette instruction pass.ident = "Charles-Henry"; fret.ident = "valises"; System.out.println(); System.out.println("Le passager est " + pass.tostring()); System.out.println("Le fret est " + fret.tostring()); 0 / Le standard Java est respecté: les variables sont déclarées au fur et à mesure de leur emploi / //Véhicule véh = new Véhicule(); // Méditer l'erreur déclenchée par cette instruction System.out.println(); System.out.println("Le véhicule voit est de type " + voit.tostring()); System.out.println("Le véhicule moto est de type " + moto.tostring()); Passager pass = new Passager(); Fret fret = new Fret(); //ChoseTransportée chose = new ChoseTransportée(); // Méditer l'erreur déclenchée par cette ins pass.ident = "Charles-Henry"; fret.ident = "valises"; System.out.println(); System.out.println("Le passager est " + pass.tostring()); System.out.println("Le fret est " + fret.tostring()); } // Client0 END TransportsClient0.
MODULE TransportsClient10; Out, TransportsAbstrait, TransportsConcret; PROCEDURE Do; véh: TransportsAbstrait.Véhicule; BEGIN (Do) véh := voit; Out.Ln; Out.String("Le véhicule est de type "+véh.tostring()); voit.nbportes := 4; ( Méditer l'erreur déclenchée par le verso de ce Fold. ) véh := moto; Out.Ln; Out.String("Le véhicule est de type "+véh.tostring()); END TransportsClient10.! TransportsClient10.Do La liaison entre le symbole "véh.tostring()" et la bonne implantation de la méthode ToString() ne peut évidemment pas se faire à la compilation (voir TransportsClient11). Elle se fait au moment de l'exécution, car c'est uniquement à ce moment-là que le type effectivement référencé est connu: il s'agit de la liaison dynamique. MODULE TransportsClient11; In, Out, TransportsAbstrait, TransportsConcret; PROCEDURE Do; véh: TransportsAbstrait.Véhicule; n: INTEGER; BEGIN (Do) In.Open; In.Int(n); IFn>0THENvéh := voit ELSE véh := moto Out.Ln; Out.String("Le véhicule est de type "+véh.tostring()); / Client10.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / import transports.; public class Client10 { Véhicule véh = voit; System.out.println("Le véhicule est de type " + véh.tostring()); //véh.nbportes = 4; // Méditer l'erreur déclenchée par cette instruction voit.nbportes = 4; véh = moto; System.out.println("Le véhicule est de type " + véh.tostring()); } // Client10 / Client11.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / import transports.; public class Client11 { int n = Integer.parseInt(args[0]); Véhicule véh; if (n > 0) véh = voit; else véh = moto; System.out.println("Le véhicule est de type " + véh.tostring()); } // Client11 END TransportsClient11.! TransportsClient11.Do -1 1 Remarques: Ici, c'est clairement à l'exécution que véh prend un type ou l'autre. La liaison avec la méthode ne peut évidemment pas se faire lors de la compilation. Ici, l'impossibilité est rendue évidente par le fait qu'il y a une saisie.
MODULE TransportsClient20; Out, TransportsAbstrait, TransportsConcret; PROCEDURE Do; PROCEDURE Print (véh: TransportsAbstrait.Véhicule); ( Procédure générique d'impression d'un véhicule. ) BEGIN (Print) Out.Ln; Out.String("Le véhicule est de type "+véh.tostring()) END Print; BEGIN (Do) Print(voit); Print(moto) / Client20.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / import transports.; public class Client20 { private static void print (Véhicule véh) { System.out.println("Le véhicule est de type " + véh.tostring()); } // print print(voit); print(moto); } // Client20 END TransportsClient20. C'est dans cet exemple que la projection prend tout son sens: en effet, celle-ci a lieu lors du passage de paramètres. Et donc, la procédure Print est capable de fonctionner pour n'importe quel véhicule; le type statique de véh sera toujours Véhicule alors que sont type dynamique sera défini lors de l'appel (d'abord Voiture, puis Moto).
MODULE TransportsPrintVéhicule; Out, TransportsAbstrait; PROCEDURE Print (véh: TransportsAbstrait.Véhicule); ( Procédure générique d'impression d'un véhicule. ) BEGIN (Print) Out.Ln; Out.String("Le véhicule est de type "+véh.tostring()) END Print; END TransportsPrintVéhicule. C'est une procédure générique. Elle est capable d'afficher le string de n'importe quel Véhicule. En particulier, on pourra l'employer avec des classes dérivées de Véhicule non encore connues au moment de la compilation de ce module. MODULE TransportsClient21; Out, TransportsConcret, TransportsPrintVéhicule; PROCEDURE Do; BEGIN (Do) TransportsPrintVéhicule.Print(voit); TransportsPrintVéhicule.Print(moto); / PrintVéhicule.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / public abstract class PrintVéhicule { public static final void print (Véhicule véh) { System.out.println("Le véhicule est de type " + véh.tostring()); } // print } // PrintVéhicule / Client21.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / import transports.; public class Client21 { PrintVéhicule.print(voit); PrintVéhicule.print(moto); } // Client21 END TransportsClient21.
MODULE TransportsConcretPlus; TransportsAbstrait, ZStrPlus; Bateau = POINTER TO RECORD (TransportsAbstrait.Véhicule) PROCEDURE (b: Bateau) Coût (nbpass: INTEGER; dist: REAL): REAL; BEGIN (Coût) RETURN 12distnbPass; ( Pourrait être affiné, ce n'est pas le but ici. ) PROCEDURE (b: Bateau) ToString (): POINTER TO ARRAY OF CHAR; BEGIN (ToString) RETURN ZStrPlus.DynStr("Bateau") END TransportsConcretPlus. Classe créée après compilation de TransportsPrintVéhicule (pour lequel le source pourrait même être perdu). MODULE TransportsClientPlus; Out, TransportsConcretPlus, TransportsPrintVéhicule; / Bateau.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / public final class Bateau extends Véhicule { return 12 dist nbpass; return "Bateau"; } // Bateau / ClientPlus.java @author Peter DAEHNE, 01.11.2005 @version 0.0 / import transports.; public class ClientPlus { Bateau bateau = new Bateau(); PrintVéhicule.print(bateau); } // ClientPlus PROCEDURE Do; bateau: TransportsConcretPlus.Bateau; BEGIN (Do) NEW(bateau); TransportsPrintVéhicule.Print(bateau); END TransportsClientPlus.