Nous avons vu dans ce cours qu'il existe différentes catégories de sous-programmes. On a d'une part les sous-programmes évènementiels et d'autre part les sous-programmes non évènementiels, qui se divisent eux même en deux sous catégories: les procédures et les fonctions.
En guise de synthèse nous allons voir ici ce qui est commun à ces différents types de sous-programmes et ce qui les différencie.
Un sous-programme n'existe (et par conséquent ne peut être utilisé) que s'il est déclaré.
La déclaration d'un sous-programme contient les instructions à exécuter. Elle défini son nom et ses paramètres éventuels.
De manière générale, la déclaration d'un sous-programme comprend une entête et un corps. L'entête contient le nom du programme et la déclaration des paramètres.
Les paramètres déclarés dans l'entête sont les paramètres formels, à ne pas confondre avec les paramètres effectifs (voir plus loin) dont la valeur est déterminée au moment de l'exécution du sous-programme.
En java, la déclaration des paramètres figure juste après le nom du sous-programme. S'il ne possède pas de paramètre, elle est simplement constituée d'une parenthèse ouvrante immédiatement suivie d'une parenthèse fermante. Sinon, on trouvera dans les parenthèses la liste des paramètres, chacun étant défini par son type et son nom:
(Type Nom, Type Nom, ...., Type Nom )
Le corps contient les instructions à exécuter. Il peut également contenir des déclarations de variables locales. Rappelons que la portée de ces variables est limitée au sous-programme dans lequel elles sont déclarées.
En Java, le corps d'un sous-programme commence par une accolade ouvrante et se termine par une accolade fermante. La déclaration d'un sous-programme est donc de la forme suivante:
... NomDuSousProgramme (Type Nom, ..., Type Nom) { Déclaration optionnelle des variables locales Instructions }
Ce qui figure avant le nom du sous-programme dépend du type de sous-programme.
L'entête d'une procédure commence par le mot clé void, qui signifie 'aucun résultat retourné'.
La déclaration d'une procédure s'écrit donc comme ceci:
void NomDeLaProcédure (Type Nom, ..., Type Nom) { Déclaration optionnelle des variables locales Instructions }
L'entête d'une fonction commence par le type du résultat qu'elle retourne. D'autre part, pour qu'elle puisse retourner un résultat, son corps doit forcément contenir (au moins) une instruction return.
La déclaration d'une fonction s'écrit donc comme ceci:
TypeResultat NomDeLaFonction (Type Nom, ..., Type Nom) { Déclaration optionnelle des variables locales Instructions }
L'entête d'un sous-programme évènementiel est générée automatiquement. Comme il s'agit d'une procédure, elle commence par void.
L'exécution d'un sous-programme évènementiel est déclenchée par un évènement, lui même déclenché (le plus souvent) par une action de l'utilisateur sur l'interface graphique du programme. Par exemple, par un clic sur un bouton.
Lorsque l'exécution d'un sous-programme évènementiel est terminée, le programme retourne à un état d'attente d'évenement.
L'exécution d'un sous-programme non évènementiel (fonction ou procédure) est déclenchée par un l'exécutuion d'un appel de sous-programme. On y trouve le nom du sous-programme suivi des paramètres effectifs entre parenthèses:
NomDuSousProgramme (Param. effectif, ..., Param. effectif)
De manière générale, un paramètre effectif est une expression qui est évaluée lors de l'exécution de l'appel de sous-programme. En particulier, il peut donc s'agir simplement d'une variable ou d'un littéral.
Les paramètres effectifs doivent être compatibles avec les paramètres formels. D'une part, il doit y avoir autant de paramètres effectifs que de paramètres formels. D'autre part, le type de chaque paramètre effectif doit être compatible avec celui du paramètre formel de même position.
L'exécution d'un appel de procédure provoque les opérations suivantes:
L'exécution d'un appel de sous-programme commence par le passage des paramètres dont le mécanisme est le même pour les procédures et les fonctions:
Les instructions contenues dans le corps du sous-programme sont ensuite exécutées avec ces valeurs de paramètres.
Lorsqu'elles ont toutes été exécutées, la mémoire allouée aux paramètres et aux variables locales est libérée. Il se produit ensuite le mécanisme du retour de sous-programme dont le principe n'est pas le même pour les procédures et les fonctions.
Dans le cas d'une procédure, le retour est simplement la continuation de l'exécution du programme à l'instruction qui suit son appel.
D'autre part, l'appel d'une procédure peut être considérée comme une instruction. Elle sera donc suivie d'un point virgule:
NomDeLaProcédure (Param. effectif, ..., Param. effectif);
Un appel de fonction au contraire n'est pas vraiment une instruction, mais doit plutot être considérée comme une expression à évaluer.
Comme toute expression, elle figure à l'intérieur d'une instruction: dans le membre droit d'une affectation, dans les paramètres effectifs d'un appel de procédure, ....
Considérons par exemple une fonction Somme avec deux paramètres a et b de type double, retournant la somme de ces deux nombres:
double Somme (double a, double b) { return a + b ;}
Cette fonction pourrait être appelée à l'intérieur d'une affectation, comme suit:
x = Somme (10,Z);
ou bien comme ceci:
z = Math.sqrt(Somme (x*x,y*y));
L'autre point particulier des fonctions est qu'elles retournent un résultat, contrairement aux procédures. Tout se passe comme si le résultat retourné par la fonction venait s'inscrire dans le code à l'endroit ou figure son appel.
Par exemple, en reprenant l'exemple précédent avec x = 3 et y = 4:
z = Math.sqrt(25.);
z = 5;
Vous êtes à présent aptes à comprendre que les 'instructions' de lecture et d'écriture de JavaETBib vues dans le premier cours sont en fait des appels de sous-programmes. JavaETBib est une librairie, c.a.d un ensemble de sous-programmes contenus dans un fichier (en l'occurence es.java) qui peut être utilisé dans n'importe quel projet.
Revenons rapidement sur les sous-programmes de cette librairie.
L'instruction de lecture' es.Lire (respectivement es.LireEntier et es.LireDouble) est en fait une fonction retournant une chaines de caractères (respectivement un int, un double) et dont le paramètre est le champ de texte depuis lequel l'information est lue. Pour lire un champ de texte dans une variable, il faut donc lui affecter le résultat retournée par une de ces fonctions.
L'instruction d'affichage es.Afficher est en réalité une procédure. Vous vous demandez peut être comment elle peut accepter un paramètre de type variable (String, int ou double), ce qui est normalement impossible d'après le cours.
Vous vous demandez peut être également, comment l'affichage d'un double peut se faire avec un paramètre et également avec deux paramètres (lorsque l'on veut préciser le nombre de chiffres après la virgule) puisque d'après le cours un sous-programme ne peut avoir qu'un nombre fixe de paramètres. Tous ces mystères seront éclaircis lorsque nous aborderons la programmation objet.