UNE APPLICATION ORIENTÉE OBJET MODÉLISATION ET PROGRAMMATION Patrick Bellot Télécom ParisTech telecom-paristech.fr 2009 1
Une Calculatrice Électronique 2
3 Notation polonaise inversée Notation infixée : (2 + 3) * (5 / 2) Notation préfixée : * + 2 3 / 5 2 Notation postfixée : 2 3 + 5 2 / * Les notations préfixées et postfixées nous dispensent de l usage des parenthèses.
Notation polonaise inversée La calculatrice gère une pile de nombres et d opérations. Pour évaluer une expression, on empile ses différents items tels qu ils apparaissent en notation postfixées. (22 + 3) * (5 / 2) s écrit 22 3 + 5 2 / * en notation postfixée. Si on lit la pile de haut en bas, lecture normale pour une pile, on a l expression en notation préfixée. Nous verrons qu une expression en notation préfixée est très facile à décoder. 4
Fonctionnement de la Calculatrice Électronique 5
6 Fonctionnement de la Calculatrice Électronique Boutons 1 à 9 : inscrit le chiffre dans le champ d entrée. Bouton Backspace : efface le dernier caractère du champ d entrée. Bouton +/- : change le signe du nombre dans le champ d entrée. Bouton Push value : empile le contenu du champ d entrée et l efface. Bouton Push "op" : empile l opération correspondante. Bouton Pop one : supprime le dernier élément empilé. Bouton Clear all : nettoie la pile et le champ d entrée. Bouton Quit : termine l application. Bouton Eval top : évalue l expression décrite par le premier élément de la pile et la remplace par sa valeur. Si l évaluation se passe mal, un message d erreur est empilé.
7 Modélisation orientée objet 1. Les expressions (déjà vu mais on y revient). 2. L interface : (a) l arrangement des composants ; (b) la programmation des comportements.
8 Les packages répertoire JCALC répertoire principal de l application contient le Makefile contient Main.java répertoire de compilation et d exécution peut être déplacé répertoire JCALC/EXPRESSIONS répertoire du package EXPRESSIONS contient les classes des expressions répertoire JCALC/INTERFACE répertoire du package INTERFACE contient les classes de l interface
9 Le Makefile JDK_VERSION = 1.1.6 # The JDK base classes JDK_CLASSES = /usr/local/jdk$(jdk_version)/lib/classes.zip # Compiling compile: @echo Compiling Java classes in $$PWD javac -classpath $$PWD:$(JDK_CLASSES) $$PWD/Main.java run: @echo Running with JDK $(JDK_VERSION) @java -classpath $$PWD:$(JDK_CLASSES) Main clean: @rm -rf./*~./*/*~ new: @rm -rf./*~./*/*~./*.class./*/*.class
10 Les expressions Expression (a) Constant Operation (a) Addition Modulo Substraction Division Multiplication
11 La classe Expression package EXPRESSIONS ; import java.lang.* ; public abstract class Expression { protected abstract int eval() ; public String evaluation() { return Integer.toString(eval()) ;
12 La classe Constant package EXPRESSIONS ; public class Constant extends Expression { private int valeur ; public Constant(int v) { valeur = v ; protected int eval() { return valeur ;
13 La classe Operation package EXPRESSIONS ; public abstract class Operation extends Expression { protected Expression leftop, rightop ; public Operation(Expression left, Expression right) { leftop = left ; rightop = right ;
14 La classe AEddition package EXPRESSIONS ; public class Addition extends Operation { public Addition(Expression left, Expression right) { super(left,right) ; // appel créateur de la superclasse protected int eval() { return leftop.eval() + rightop.eval() ;
15 La classe Substraction package EXPRESSIONS ; public class Substraction extends Operation { public Substraction(Expression left, Expression right) { super(left,right) ; protected int eval() { return leftop.eval() - rightop.eval() ;
16 La classe Multiplication package EXPRESSIONS ; import java.lang.* ; public class Multiplication extends Operation { public Multiplication(Expression left, Expression right) { super(left,right) ; protected int eval() { return leftop.eval() * rightop.eval() ;
17 La classe Division package EXPRESSIONS ; import java.lang.* ; public class Division extends Operation { public Division(Expression left, Expression right) { super(left,right) ; protected int eval() { return (int)(leftop.eval() / rightop.eval()) ; // problème!!!!!
18 Les Erreurs en Java Exécution normale main p q r s
19 Les Erreurs en Java Une erreur se traduit par une exception. Exécution avec une erreur non traitée Programme stoppé main Propagation de l exception p q r s ERREUR Une exception est un objet de la classe Exception ou d une de ses classes dérivées. Elle contient des informations sur l erreur. Une exception non traitée provoque l arrêt du programme. Il y a des exceptions déclenchées par le langage et des exceptions définies et déclenchées par le programmeur.
20 Traitement d une erreur en Java Exécution avec une erreur traitée Traitement et reprise de l exécution Propagation de l exception ERREUR main p q r s try { // instructions susceptible de produire une erreur // du type TypeException...... catch(typeexception e) { // traitement de l exception...
21 La classe Division On doit déclarer la survenue possible d erreurs. package EXPRESSIONS ; import java.lang.* ; public class Division extends Operation { public Division(Expression left, Expression right) { super(left,right) ; protected int eval() throws ArithmeticException { // on déclare le type de l exception susceptible de déclenchement return (int)(leftop.eval() / rightop.eval()) ;
L exception ArithmeticException est définie par le langage. Elle est déclenchée en cas de division par zéro. 22
23 La classe Modulo package EXPRESSIONS ; import java.lang.* ; public class Modulo extends Operation { public Modulo(Expression left, Expression right) { super(left,right) ; protected int eval() throws ArithmeticException { return (int)(leftop.eval() % rightop.eval()) ;
24 Construction d une expression Expression e ; // e est une référence sur des objets de type Expression e = new Addition(new Constant(34),new Division(new Constant(23), new Constant(2)) ; // e = 34 + (23 / 2) int r ; Évaluation d une expression try { r = e.eval() ; catch(arithmeticexception ae) { System.out.println("*** Error" + ae.getmessage()) ; ;
25 package EXPRESSIONS ; import java.lang.* ; Le traitement des Erreurs arithmétiques public abstract class Expression { protected abstract int eval() throws ArithmeticException ; public String evaluation() { try { return Integer.toString(eval()) ; catch(arithmeticexception e) { return e.getmessage() ; ;
Une Calculatrice Électronique 26
27 Attributs: W P JcalclWindow EntryPanel à pour attribut L Label E Textfield L B B B W : P : B : L : L : * / mod classe dérivée de classe dérivée de classe dérivée de classe dérivée de classe dérivée de P B B + - Frame Panel Button List Label OpsPanel P B B B P Panel StackList DigitsPanel 0 1 +/- B B B B Eval top Pop one Clear all Quit On décide que tous connaîtront la fenêtre principale.
28 La notion de Layout Un objet de la classe Layout définit comment les composants sont positionnés et dimensionnés dans une fenêtre ou un Panel. Il est associé par la méthode setlayout(<layout>). Container c ; // Frame est une classe dérivée de Container // Panel est aussi dérivée de Container c.setlayout(new FlowLayout()) ; // un layout particulier c.add(a) ; c.add(b) ; c.add(x) ; c.add(d) ; c.add(e) ; // ajoute le composant a suivant le layout // ajoute le composant b suivant le layout // ajoute le composant x suivant le layout // ajoute le composant d suivant le layout // ajoute le composant e suivant le layout
29 Trois layouts particuliers : c.setlayout(new FlowLayout()) c.setlayout(new BorderLayout()) a b c c.add(a) ; c.add(b) ; c.add(c) ; a b x d e c.add(a,"north") ; c.add(b,"west") ; c.add(x,"center" ; c.add(d,"east") ; c.add(e,"center") ; c.setlayout(new GridLayout(4,2) a b x d e f g h c.add(a) ; c.add(b) ;...... c.add(g) ; c.add(h) ;
30 La fenêtre principale package INTERFACE ; import java.awt.* ; import EXPRESSIONS.* ; public class JcalcWindow extends Frame { // les widgets de Java // package des expressions // Frame = fenêtre public JcalcWindow() { super("jcalc calculator") ; setlocation(100,100) ; setsize(656,485) ; setfont(new Font("Serif",Font.BOLD,16)) ; createwidgets() ; show() ; // initialisation // initialisation avec la super méthode // quelques parametres // créer les widgets // faire apparaître Le comportement des widgets (composants) est fait à leur création.
31 // Dans la classe JcalcWindow Création des composants private DigitsPanel digitspanel ; // les widgets de la fenetre private StackList stacklist ; private EntryPanel entrypanel ; private OpsPanel opspanel ; private void createwidgets() { setlayout(new BorderLayout()) ; add(digitspanel = new DigitsPanel(this), "Center") ; add(stacklist = new StackList(this), "East" ) ; add(entrypanel = new EntryPanel(this), "North" ) ; add(opspanel = new OpsPanel(this), "South" ) ; Les classes des composants restent à définir. On leur donne this, c est-à-dire la fenêtre, en paramètre cela servira à programmer leurs comportements.
32 Le panneau des chiffres package INTERFACE ; import java.awt.* ; import INTERFACE.* ; public class DigitsPanel extends Panel { public DigitsPanel(JcalcWindow jwindow) { setlayout(new GridLayout(4,3)) ; for (int i=9 ; i>=1 ; i--) add(new DigitButton(jWindow,i)) ; add(new BackSpaceButton(jWindow)) ; add(new DigitButton(jWindow,0)) ; add(new PlusMoinsButton(jWindow)) ;
33 Le bouton chiffre package INTERFACE ; import java.awt.* ; import INTERFACE.* ; public class DigitButton extends Button { private JcalcWindow jwindow ; public DigitButton(JcalcWindow j, int i) { super(integer.tostring(i)) ; jwindow = j ;
34 Le bouton backspace package INTERFACE ; import java.awt.* ; import INTERFACE.* ; public class BackSpaceButton extends Button { private JcalcWindow jwindow ; public BackSpaceButton(JcalcWindow j) { super("backspace") ; jwindow = j ;
35 Le bouton plus/moins package INTERFACE ; import java.awt.* ; import INTERFACE.* ; public class PlusMoinsButton extends Button { private JcalcWindow jwindow ; public PlusMoinsButton(JcalcWindow j) { super("+/-") ; jwindow = j ;
36 La pile package INTERFACE ; import java.awt.* ; import INTERFACE.* ; import EXPRESSIONS.* ; public class StackList extends List { private JcalcWindow jwindow ; public StackList(JcalcWindow j) { super(20) ; jwindow = j ;
37 La programmation des comportements On peut programmer le comportement des composants graphiques lors des évènements provoqués par l utilisateur et/ou transmis par le système. Ce sont des objets associés au composant graphique qui gère cela. Composant graphique (widget) Listener n. 1 Listener n. 2 Une suite de Listener par type d événement pouvant arriver au composant. Chaque Listener possède une méthode de nom particulier prenant en argument un objet Listener n.3
Exemple : le bouton Quit 38
39 package INTERFACE ; import java.awt.* ; import java.awt.event.* ; // le package des événements import INTERFACE.* ; public class QuitButton extends Button { private JcalcWindow jwindow ; public QuitButton(JcalcWindow j) { super("quit") ; jwindow = j ; addactionlistener(new Action()) ; // le listener (add) class Action implements ActionListener { // attention : inner class public void actionperformed(actionevent e) { // l action jwindow.quit() ; // demande à la fenêtre
40 // Dans la class JcalcWindow protected void quit() { Exemple : le bouton Quit // il pourait y avoir des sauvegardes a effectuer System.out.println("Jcalc terminated, bye!") ; System.exit(0) ;
41 Exemple : le bouton Eval top Expression e ; // e est une référence sur des objets de type Expression e = new Addition(new Constant(34),new Division(new Constant(23), new Constant(2)) ; // e = 34 + (23 / 2)
42 En fait, dans notre application tous les composants s adressent à la fenêtre. C est un choix personnel. On a transmis la fenêtre à tous les composants pour qu ils puissent s adresser à elle. Remarquons que pour l évaluation, la StackList suffisait. On aurait pu transmettre cette StackList au bouton Eval top et ce dernier aurait pu s adresser à elle. Cependant, dans ce cas, il faut créer la StackList avant le bouton Eval top, ce qui impose une chronologie dans les créations. Notre méthode évite ces contraintes chronologiques dans les créations en échange de la définition d un certain nombre de méthodes relais dans la classe de la fenêtre principale. Une méthode généralement adoptée est de créer tous les widgets sans programmation des comportements puis de programmer les widgets lorsqu on est sûr que tous sont disponibles pour la programmation.
43 Exemple : le bouton Eval top int r ; try { r = e.eval() ; catch(arithmeticexception ae) { System.out.println("*** Error" + ae.getmessage()) ; ;
44 L exception MalformedStack package INTERFACE ; import java.awt.* ; public class MalformedStack extends Exception { public MalformedStack(String s) { super(s) ;
45 // Dans la classe StackList import EXPRESSIONS.* ; La méthode getexpression() public Expression getexpression() throws MalformedStack { if (getitemcount() == 0) throw new MalformedStack("Not enough operands") ; String first = getitem(0) ; remove(0) ; if (first.compareto("+") == 0) return new Addition(getExpression(),getExpression()) ;... try { return new Constant(Integer.parseInt(first)) ; catch(numberformatexception e) { throw new MalformedStack("Bad number syntax") ; ;
46 Remarques trois heures de programmation ; documentation en ligne sur Java et ses classes.