6.2.2 La calculatrice
Pour qu’une calculatrice puisse livrer un résultat, elle doit
recevoir deux nombres et un opérateur. Suivant l’ordre dans
lequel elle reçoit ces arguments, nous parlerons d’une calculatrice
postfixe7, d’une calculatrice
infixe8 ou encore d’une
calculatrice préfixe9.
6.2.2.1 développement du modèle de la calculatrice
Commençons en vue d’une
calculatrice postfixe.
De toute façon, toute calculatrice a besoin d’un écran, nous l’appelons
bufferEcran, d’un accumulateur (accu), pour garder les résultats obtenus
jusqu’à maintenant, et d’un indicateur, firstTime, qui doit être true si l’on
commence à écrire un nouveau nombre sur l’écran, et false quand le chiffre juste
entré doit être concatené au nombre partiel déjà sur l’écran.
Voici alors la définition de la classe Calculatrice:
Model subclass: #Calculatrice
instanceVariableNames: ’accu bufferEcran firstTime’
classVariableNames: ’’
poolDictionaries: ’’
category: ’Cours-Smalltalk’
|
|
et sa méthode d’initialisation:
Calculatrice>>initialize
accu := 0.
bufferEcran := accu asString.
firstTime := true
|
|
Puisque les instances de la classe Touche communiquent avec la calculatrice
via le couple de messages changed: et update: nous devons determiner
comment réagir à l’activation d’une touche. Le plus simple est de lancer la
fonctionnalité associée à la touche. Nous allons associer aux touches numériques
la fonctionnalité activeNumber:, aux touches des opérateurs +, -, × et
/ les opérations arithmétiques correspondantes à l’aide d’une méthode
activeFonction:, et à la touche C, pour Clear, la fonctionnalité activeClear:.
Ce raisonnement nous donne déjà les deux méthodes suivantes pour reinitialiser
la calculatrice, activeClear:, et pour traiter les touches numériques,
activeNumber::
Calculatrice>>activeClear: label
self initialize
|
|
Calculatrice>>activeNumber: label
firstTime
ifTrue: [firstTime := false.
bufferEcran := label]
ifFalse: [bufferEcran size = 1 & ((bufferEcran at: 1)
= $0)
ifTrue: [bufferEcran := ’’].
bufferEcran := bufferEcran , label]
|
|
La deuxième méthode distingue entre le cas ou l’on commence à écrire un nombre
et les autres cas. Si c’est le début de l’écriture d’un nombre, on initialise la
variable d’instance bufferEcran avec le chiffre correspondant à la touche activée
et transmis dans l’argument label comme une chaîne de caractère. Sinon, après
avoir enlevé le ’zéro’ éventuellement affiché sur l’écran, on concatène ce chiffre au
nombre déjà contenu dans la variable bufferEcran. Ainsi l’écran contiendra un
nombre et, dans tous les cas, on est sûr d’être sorti de l’état où firstTime est
true.
Pour l’implémentation des autres fonctionnalités nous devons prendre une
décision: voulons-nous une calculatrice postfixe ou infixe? Puisque dans une
calculatrice infixe l’interprétation de la touche =, par exemple, implique le
lancement de l’opération arithmétique préalablement entrée, pendant que
l’interprétation de la même touche dans une calculatrice postfixe ne peut qu’être
le transfer du contenu de bufferEcran vers l’accumulateur, la variable d’instance
accu.
Commençons alors par construire une calculatrice postfixe: elle a l’air plus simple.
Néanmoins, en prévision de la construction ultérieure d’une calculatrice infixe (et
pourquoi pas préfixe aussi), mettons les méthodes spécifiques à une manière de
calculer dans une sous-classe spécifique. Pour notre calculatrice postfixe nous
créons la sous-classe CalculatricePostfixe:
Calculatrice subclass: #CalculatricePostfixe
instanceVariableNames: ’’
classVariableNames: ’’
poolDictionaries: ’’
category: ’Cours-Smalltalk’
|
|
Dans cette sous-classe nous allons définir les deux méthodes activeEgal: et
activeFonction: comme suit:
CalculatricePostfixe>>activeEgal: label
accu := bufferEcran asNumber.
firstTime := true
|
|
La méthode activeFonction: doit considerer les contenus des deux variables
d’instances accu et bufferEcran comme les opérandes de l’opérateur donné par
l’étiquette de la touche fonction qui a été activée. Ce qui donne:
CalculatricePostfixe>>activeFonction: label
accu := accu perform: label asSymbol
with: bufferEcran asNumber.
bufferEcran := accu printString.
firstTime := true
|
|
Il ne nous reste qu’à écrire la méthode d’interface avec les touches, la méthode
update:, qui doit activer la méthode donnée dans la variable d’instance fonction
de la touche, avec comme argument l’étiquette de cette même touche. Ce qui nous
donne la définition suivante:
Calculatrice>>update: aTouche
self perform: aTouche fonction with: aTouche label
|
|
Voilà. Nous avons terminé l’écriture du noyau d’une calculatrice postfixe, du
modèle d’une telle calculatrice.
6.2.2.2 test du modèle de la calculatrice
Avant de continuer le développement
de notre calculatrice, nous présentons ci-dessous, une petite méthode permettant
de vérifier le bon fonctionnement du modèle:
CalculatricePostfixe class>>exemple
"CalculatricePostfixe exemple"
| aCalc t1 tPlus tEgal tCE |
aCalc := self new.
t1 := Touche new
label: ’1’
fonction: #activeNumber:
on: aCalc.
tPlus := Touche new
label: ’+’
fonction: #activeFonction:
on: aCalc.
tEgal := Touche new
label: ’=’
fonction: #activeEgal:
on: aCalc.
tCE := Touche new
label: ’C’
fonction: #activeClear:
on: aCalc.
self halt
|
|
Ici nous procédons comme dans la section 6.1.3: nous utilisons une combinaison
entre le débogguer et des inspecteurs pour obtenir une première impression sur la
correction du programme.
Si nous activons l’expression CalculatricePostfixe exemple nous
obtenons la fenêtre déboggueur donnée dans la figure 6.13.
Nous avons accès à une touche numérique, la touche t1, une touche
arithmétique, la touche tPlus, la touche tEgal correspondant à la touche
=, et la touche tCE pour la réinitialisation. Bref, nous avons une touche
pour chacune des quatres méthodes d’interprétation possible des touches.
Nous pouvons alors ouvrir un inspecteur sur la calculatrice et des
inspecteurs sur chacune de ces touches pour les activer et observer leurs
effets.
La figure 6.14 montre en haut un inspecteur ouvert sur la touche t1 et en bas
un autre ouvert sur la touche tPlus. L’inspecteur en haut dans la figure 6.15
montre l’état de notre calculateur postfixe après avoir
-
- activé la touche t1, par l’évaluation de la transmission self activer
dans la fenêtre d’interaction de l’inspecteur sur cette touche (cf.
l’inspecteur à gauche dans la figure 6.14);
-
- activé la touche tEgal (non montré dans les figures) de la même
manière, ce qui avait comme effet que l’accumulateur accu
prenait la valeur 1 (visible dans l’inspecteur gauche de la figure
6.15);
-
- activé trois fois la touche t1, ce qui avait comme effet que la variable
bufferEcran prenait la valeur ’111’ (visible dans l’inspecteur
gauche de la figure 6.15).
L’inspecteur en bas dans la figure 6.15 montre l’état de notre calculatrice après
avoir activé ensuite la touche d’addition tPlus (visible en bas dans la figure
6.14).
Visiblement, notre calculateur est en bonne voie: le modèle semble fonctionner
correctement car l’accumulateur accu contient la somme des deux nombres que
nous avons entré. Il nous reste à devélopper des vues pour cette calculatrice, pour
pouvoir l’utiliser interactivement, en cliquant sur des touches et en observant les
effets dans des fenêtres de cette calculatrice. Allons-y.