Algorithmique & Programmation Orientée Objet Semestre 2 ST Structuration des programmes en sous-algorithmes
| Problématiques | Programmation modulaire | Sous-algorithme | Syntaxe Algorithmique |
| Paramètres de type agrégé en entrée en sortie et en retour en PDL | Syntaxe Java | Paramètres en entrée, en sortie et en retour en langage Java | Recommandations |
Cours | Exercices PDL | Exercices Java
Version PDF
Clavier.class - Ecran.class - Documentation
Problématique n°1 Comment développer de grosses applications quand on ne dispose que du "for", du "while", du "if" et du "case" pour structurer l'algorithme principal? Solution Utiliser un outil de développement permettant de diviser un gros problème complexe en un ensemble de sous-problèmes - plus petits, - individuellement moins complexes, - aussi indépendants les uns des autres que possible Résoudre ces sous-problèmes Assembler les solutions Exemple Concevoir une voiture est un problème d'une grande complexité. Décomposition en un ensemble de problèmes consistant à concevoir: Une carrosserie Un habitacle Un moteur Une transmission Une direction Un système de freinage Un système d'éclairage ... Avantages Méthode de conception constituant en tant que telle une méthode d'analyse Conception globale simplifiée Solution de chaque problème élémentaire validable individuellement Validation globale simplifiée si certitude de la validation de chaque solution élémentaire Résolution indépendante possible de chaque problème élémentaire: Travail simultané de plusieurs développeurs -> Développement accéléré Affectation des problèmes à des spécialistes du domaine -> Meilleurs développements Inconvénients L'ensemble des solutions élémentaires concourt à la résolution du problème global -> Solutions élémentaires non totalement indépendantes les unes des autres -> Conception de l'interaction entre les solutions élémentaires: Problème en soi Décomposition en sous-problèmes pas toujours possible Problématique n°2 Comment éviter de résoudre plusieurs fois un même problème quand celui-ci apparait plusieurs fois dans la même application ou dans des applications différentes? Comment faciliter la réutilisation de codes informatiques que l'on a développés? Comment faciliter l'utilisation de codes informatiques par d'autres personnes que celles qui les ont conçus? Solution Utiliser une technique de développement permettant d'"englober" la résolution algorithmique d'un problème de manière qu'il soit possible de faire appel à l'algorithme sans le réécrire - Eventuellement sans même avoir accès au code source de l'algorithme - Eventuellement sans même connaître de façon précise comment fonctionne l'algorithme Exemples En langage Java: Math.sin(x) -> Calcul de sinus(x) et "retour" du résultat de ce calcul "Fonction" standard du langage Java En langage Java: Clavier.saisirInt() -> Lecture au clavier d'une valeur de type java int et "retour" du résultat de cette opération de lecture "Fonction" non standard de Java (développée ad hoc pour les séances de TP -> Utilisation du fichier Clavier.class) Avantages Technique algorithmique guidant l'analyse Réutilisation d'algorithmes développés et validés par soi-même ou par d'autres developpeurs Conception de vastes bibliothèques d'algorithmes (librairies, API (Application Programming Interface)) Exemples: Ecran.class, Clavier.class, l'API Java Correction des bugs plus facile Trouver l'algorithme où est présent le bug Le corriger dans cet algorithme Correction automatiquement déployée partout où l'algorithme est utilisé Inconvénients Aucun Programmation modulaire à base de sous-algorithmes Sous-algorithme: Algorithme informatique développé dans le but d'être "utilisé dans" (appelé depuis) d'autres algorithmes Diverses dénominations pour désigner le concept de "sous-algorithme" suivant divers contextes de développement: Fonction (terme usuel): Programmation structurée (C, Pascal, Basic, Fortran, ADA, Java, Javascript, PHP, ...) Programmation fonctionnelle (Lisp, Caml, ...) Algorithmique PDL Procédure: Programmation structurée (Pascal, ...) Méthode: Programmation orientée objet (Java, C++, C#, ...) Sous-programme: Programmation structurée Sous-algorithme: Algorithmique PDL Action: Algorithmique PDL Exemple n°1: Calcul de la valeur d'un polynôme Problème: Ecrire un algorithme de calcul de f(x,m,n) = xm+xn où x est réel (différent de 0.0) et m et n sont des entiers positifs ou nuls. x, m et n sont acquis au clavier. Le résultat du calcul est affiché à l'écran.
Analyse Donnée(s) du problème: Valeur x de l'énoncé: nommée x et définie de type réel Valeur m de l'énoncé: nommée m et définie de type entier Valeur n de l'énoncé: nommée n et définie de type entier Résultat(s) du problème: Valeur f(x,m,n) de l'énoncé: nommée res et définie de type réel Traitements Calcul de la première puissance: Si m = 0, xm = 1.0 sinon xm = x * x * x* ... *x (m-1 multiplications réalisées au moyen d'une boucle pour) Calcul de la seconde puissance: Si n = 0, xn = 1.0 sinon xn = x * x * x * ... * x (n-1 multiplications réalisées au moyen d'une boucle pour) Somme des deux puissances Conception en langage algorithmique:
action principale() réel x entier m,n réel res entier i réel res1,res2 x <- saisir() m <- saisir() n <- saisir() si m == 0 alors // \ res1 <- 1.0 // | sinon // | res1 <- x // -- (1) pour i de 1 à m-1 faire // | res1 <- res1 * x // | fait // | fsi // / si n == 0 alors // \ res2 <- 1.0 // | sinon // | res2 <- x // -- (2) pour i de 1 à n-1 faire // | res2 <- res2 * x // | fait // | fsi // / res <- res1 + res2 afficher("f(x,m,n) = ",res) fin action
Blocs de code (1) et (2) très semblables (m pour n, res1 pour res2) Normal car ces blocs réalisent tous deux le calcul d'une puissance entière de x (une première fois avec n comme puissance, une seconde fois avec m) Exploitation de cette ressemblance pour simplifier l'écriture de notre action principale: -> Ecriture d'un sous-algorithme (une fonction) de calcul de la puissance entière d'un nombre réel -> Utilisation de ce sous-algorithme dans l'action principale une première fois à la place du bloc (1) et une seconde fois à la place du bloc (2) Syntaxe souhaitée après réécriture:
action principale() réel x entier m,n réel res réel res1,res2 x <- saisir() m <- saisir() n <- saisir() res1 <- puissance(x,m) // (1) res2 <- puissance(x,n) // (2) res <- res1 + res2 afficher("f(x,m,n) = ",res) fin action
Deux paramètres pour le sous-algorithme développé appelé puissance: Dans l'ordre: Un réel (nommons le v) Un entier (nommons le n) Calcul de la puissance n de v "Retour" de cette valeur
Sous-algorithme Conçu pour réaliser un traitement Bien défini Bien délimité Si possible de manière parfaitement indépendante au contexte particulier de l’algorithme appelant pour qu'il puisse être utilisé dans n'importe quel contexte Généralement muni de paramètres "passés" en entête 0, 1 ou plusieurs paramètres correspondant aux "données" du traitement réalisé par le sous-algorithme -> Paramêtre(s) transmis en "entrée" par copie de l'algorithme appelant vers le sous-algorithme appelé 0, 1 ou plusieurs paramètres correspondant aux "résultats" du traitement réalisé par le sous-algorithme -> Paramètre(s) transmis en "sortie" par copie du sous-algorithme appelé vers l'algorithme appelant Problèmes résolus par ce biais: - Communication des données de l'algorithme appelant à destination du sous-algorithme appelé - Communication des résultats du sous-algorithme appelé à destination de l'algorithme appelant Optionnellement muni de variables locales Utilisation possible de variables temporaires locales au sous-algorithme (non définies en dehors) pour en assurer le traitement Comment déterminer les paramètres d'entrée et de sortie? Analyser l'énoncé du problème car celui-ci est généralement précis sur cette question En cas d'imprécision, responsabilité du choix laissée à la personne qui réalise l'analyse Syntaxe en langage algorithmique Un entête (extrêmement important car il définit comment le sous-algorithme pourra être appelé par l'algorithme appelant): Le nom du sous-algorithme (par l'intermédiaire duquel il sera désigné lors d'un appel) La liste des paramètres "formels" transmis avec indication de leurs noms, types et modificateurs (paramètre en entrée, en sortie ou en entrée/sortie) tels qu'ils sont connus dans le corps du sous-algorithme Une zone de définition pour d'éventuelles variables locales Un corps de réalisation de tous les traitements de calcul des paramètres en sortie à partir des paramètres en entrée (en utilisant les variables locales à titre de variables intermédiaires de traitement) Syntaxe:
action nom_action(liste exhaustive des triplets (noms,type,modificateur) des parametres formels) déclarations des variables locales de traitement corps du sous-algorithmeclass="couleurBloc"> corps du sous-algorithme fin action
Liste exhaustive des noms des paramètres Le séparateur est la virgule. Utilisation de la syntaxe type nomParametre pour chacun d'eux Utilisation du signe -> placé avant type nomParametre pour indiquer un paramètre en entrée Utilisation du signe -> placé après type nomParametre pour indiquer un paramètre en sortie Zone de définition des variables locales de traitement Déclaration de toutes les variables locales au sous-algorithme Utilisation de la syntaxe type nomVariable pour chacun d'elles Appel à un sous-algorithme Appel à un sous-algorithme au moyen d'une instruction formatée sous la forme: nom_action(liste de parametres) où les paramètres "effectifs" de la liste d'appel sont donnés dans le bon ordre (celui des paramètres formels). Lors de l'exécution: - Copie des paramètres effectif vers les paramètres formels correspondant de l'entête du sous-algorithme passés en entrée -> Les paramètres d'appel peuvent être des variables, des constantes, des constantes littérales, des expressions, ... (i.e. toute "chose" pouvant être évaluée pour obtenir la valeur qui sera transmise par copie) - Exécution du corps du sous-algorithme au moyen des paramètres formels en entrée et des variables locales dans le but d'affecter les paramètres formels en sortie avec les valeurs nécessaires - Copie des paramètres formels du sous-algorithme passés en sortie vers les paramètres effectifs correspondants. -> Obligation pour ces paramètres d'appel d'être des variables car l'opération d'affectation doit être possible. Nom des sous-algorithmes Lettres non accentuées, chiffres et _ autorisés Interdiction de débuter par un chiffre Conventions Ecriture en minuscule Si nom composé, à l'exception de la première, initiale de chaque item en majuscule Recommandation: Nom choisi de manière explicite vis à vis du traitement réalisé Exemples: testEgalite, saisirEntier Même nom possible pour deux sous-algorithmes si les listes de types extraites de leurs listes de paramètres d'entête sont différentes. Exemple
action puissance(-> réel v,-> entier n,réel p ->) entier i si n == 0 alorsloc"> si n == 0 alors p <- 1.0 sinon p <- v pour i de 1 à n-1 faire p <- p*v fait fsi fin action
Réalisation de l'analyse visant à déterminer les données, les résultats et les traitements à réaliser pour implanter le problèmeliser pour implanter le problème Les données sont les paramètres formels en entrée. Elles sont passées en entête et n'ont donc pas à être acquises dans le sous-algorithme. Les résultats sont les paramètres formels en sortie. Ils sont passés en entête et n'ont donc pas à être exploités dans le sous algorithme. Les traitements constituent le corps.raitements constituent le corps. Cas particulier: Sous-algorithme sans entrée et/ou sans sortie Exemple: Ecran.afficher(a,b), deux entrèes, pas de sortie Exemple: Ecran.sautDeLigne(), ni entrée, ni sortie Possiblement aucun paramètre d'entête en entrée Possiblement aucun paramètre d'entête en sortie Cas particulier: Sous-algorithme avec acquisition interne des données et/ou exploitation interne des résultats Si l'énoncé du problème le justifie: Acquisition des données du traitement (définies au moment de l'analyse) directement au sein du sous-algorithme (clavier, fichier, réseau, ...) et non en entrée en entête Si l'énoncé du problème le justifie: Exploitation des résultats du traitement (définis au moment de l'analyse) directement au sein du sous-algorithme (affichage à l'écran, écriture dans un fichier, ...) sans transmission en sortie en entête Conséquences: - Possiblement aucun paramètre d'entête en entrée - Possiblement aucun paramètre d'entête en sortie Exemples n°2 Enoncé (1) Ecrire un sous-algorithme qui réalise les traitements suivants: Lecture au clavier d'un paramètre de type réel Calcul du carré de ce paramètre Affichage de la valeur obtenue Mini-analyse: Une seule donnée de traitement acquise au clavier au sein du sous-algorithme donc non passée en entrée en entête Un seul résultat de traitement directement affiché et donc non passé en sortie en entête de sous-algorithme Enoncé (2) Ecrire un sous-algorithme de calcul du carré d'un réel Mini-analyse: Une seule donnée de traitement acquise en entrée en entête Un seul résultat de traitement passé en sortie en entête de sous-algorithme Implantation de l'énoncé 1 de exemple n°2
action carreEnnonce1() réel x réel res afficher("SVP, valeur? ") x <- saisir() res <- x*x afficherln(x," au carre = ",res) fin action
Implantation de l'énoncé 2 de exemple n°2
action carreEnnonce2(-> reel x,reel res ->) res <- x*x fin action
A l'avenir, utilisation du mot réservé "fonction" pour les sous-algorithmes à valeur retournée, utilisation du mot réservé "action" pour les sous-algorithmes sans valeur retournéelgorithmes sans valeur retournée
type fonction nom_fonction(liste exhaustive des triplets (noms,type,modificateur) des parametres formels) déclarations de variables dont une variable v (*) retournée en fin d'action corps du sous-algorithmep; dont affectation de v avec la valeur à retourner retourner v fin fonction"couleurMotReserve">fin fonction
(*) Nom de variable choisi arbitrairement
Type de donnée indiqué avant le mot réservé fonction: Type de la valeur "retournée" (rendue, renvoyée) par la fonction Présence dans la fonction parmi les variables locales d'une variable spécifique dédiée du type retournéécifique dédiée du type retourné Affectation obligatoire de cette variable avec la valeur que l'on souhaite retourner Utilisation de l'instruction retourner juste avant le Exemple d'appel à ce sous-algorithme: Affectation du résultat d'exécution à une variable variable <- nom_fonction(parametres effectifs) où les paramètres d'appel sont séparés par des virgules et apparaissent dans l'ordre de définitiont dans l'ordre de définition Appel direct autorisé au sein d'une expression: Ecran.afficherln(nom_fonction(parametres effectifs)) Implantation alternative de l'énoncé 2 de exemple n°2de l'énoncé 2 de exemple n°2
réel fonction carreEnnonce2(-> réel x) réel res res <- x*x retourner res fin fonction
Implantation de l'exemple n°1
réel fonction puissance(-> reel v,-> entier n) réel p entier i si n == 0 alors p <- 1.0 sinon p <- v pour i de 1 à n-1 faire p <- p * v fait fsi retourner p fin fonction action principale() réel x entier m,n réel res réel res1,res2 x <- saisir() m <- saisir() n <- saisir() res1 <- puissance(x,m) res2 <- puissance(x,n) res <- res1 + res2 afficher("f(x,m,n) = ",res) fin action
Seconde implantation de l'exemple n°1
réel fonction puissance(-> réel v,-> entier n) réel p entier i si n == 0 alors p <- 1.0 sinon p <- v pour i de 1 à n-1 faire p <- p * v fait fsi retourner p fin fonction réel fonction polynome(-> réel x,-> entier m,-> entier n) réel res res <- puissance(x,m)+puissance(x,n) retourner res fin fonction action principale() réel x entier m,n réel res x <- saisir() m <- saisir() n <- saisir() res <- polynome(x,m,n) afficher("f(x,m,n) = ",res) fin action
Passages de paramètres de type agrégé en entrée, en sortie et en retour Utilisation de paramètres de types agrégés en entrée, en sortie et en retour autorisée en langage algorithmique Support de tous les types de passages en paramètre: En entrée En sortie En entrée/sortie En retour Exemple: Sous-algorithme de calcul de l'intersection de deux droites du plan Développement d'un type agrégé coordonnées2D Deux paramètres en entrée pour passer les deux droites Possibilité de développer deux variantes de sous-algorithme: - Une fonction avec une valeur de type coordonnées2D retournée - Une action avec un paramètre d'entête en sortie de type coordonnées2D
{ Structure de stockage de coordonnees reelles } { en deux dimensions } structure coordonnees2D reel x <- 0.0 { Abscisse } reel y <- 0.0 { Ordonnee } fin structure { Type agrege de stockage des composantes } { reelles d'une droite du plan } structure droite2D reel a <- 0.0 { Coefficient directeur } reel b <- 0.0 { Ordonnee a l'origine } fin structure { Calcul de l'intersection entre deux droites } { non paralleles d'équation y = a*x+b } { Implantation sous la forme d'une fonction } coordonnees2D fonction intersection(-> droite2D d1,-> droite2D d2) coordonnees2D inter inter.x <- (d2.b-d1.b)/(d1.a-d2.a) inter.y <- d1.a*inter.x+d1.b retourner inter fin fonction { Calcul de l'intersection entre deux droites } { non paralleles d'équation y = a*x+b } { Implantation sous la forme d'une action } action intersection(-> droite2D d1,-> droite2D d2,coordonnees2D inter ->) inter.x <- (d2.b-d1.b)/(d1.a-d2.a) inter.y <- d1.a*inter.x+d1.b fin action { Action principale } action principale() droite2D da; droite2D db; coordonnees2D c1; coordonnees2D c2; { Saisie de da } ... { Saisie de db } ... { Appel a la fonction intersection } c1 <- intersection(da,db); { Appel a l'action intersection } intersection(da,db,c2); { c1 et c2 contiennent les memes coordonnees } afficherln(c1.x," ",c1.y) afficherln(c2.x," ",c2.y) fin action
IntersectionDroites2D.lda
Si implantation d'une fonction, obtention d'un retour de type agrégé qui peut être utilisé pour affectation à une variable (affectation champ pour champ au moyen de l'opérateur <-), inclusion dans une expression, passage à une fonction, ... Implantation de sous-algorithmes en langage Java Dénomination: "fonction" en programmation classique, "méthode" en programmation orientée objet Application Java: Obligatoirement une fonction main d'entête "public static void main(Strings [] args)" Fonction main implicitement exécutée au lancement de l'application Présence possible d'autres fonctions que la fonction main: Fonctions incluses dans la classe application au dessus ou en dessous de la fonction main (pas à l'intérieur) Entête d'une fonction Java
Syntaxe de l'entête de toute fonction Java ayant des paramètres:
static type nomFonction(type param1, type param2, ..., type paramN)
Paramètres d'entête indiqués sous la forme d'une liste avec le caractère virgule comme séparateur Type de chacun d'eux spécifié dans la liste avant son nom Pas de spécification explicite de modificateurs semblables aux modificateurs entrée, sortie et entrée/sortie du langage algorithmique Nom de la fonction choisi selon les mêmes conventions que les noms de variable Même nom possible pour deux fonctions si les listes de types extraites de leurs listes de paramètres d'entête sont différentes.s d'entête sont différentes.
Si fonction sans paramètre, syntaxe de l'entête:
static type nomFonction()
Nom de type juste après le mot réservé static: Type de l'unique valeur retournée par la fonction Utilisation du type "void" (vide en anglais) si pas de valeur retournée Emploi de void comme type de valeur retournée obligatoire pour de telles fonctions Fonctions nommées "fonction void" Corps d'une fonction Java Une zone de déclaration de variables locales Une zone de réalisation des traitements
Si fonction avec valeur retournée (fonction "non void"), dernière instruction de traitement:
returnclass="couleurMotReserve">return valeur;
valeur: Une variable du type retourné spécifié en entête
Si fonction sans valeur retournée (fonction "void"): Aucune instruction return (rendre quoi?)

Appel à une fonction Java

- Syntaxe identique à la syntaxe algorithmique:
  - Le nom de la fonction suivi, entre parenthèses, de la liste des paramètres sur lesquel l'appel est réalisé
  - Si fonction non void, obtention d'un retour qui peut être utilisé pour affectation à une variable, inclusion dans une expression, passage à une fonction, ...

Implantation Java de l'exemple n°1

public class Polynome { /* Calcul de la puissance entiere d'un reel */ static double puissance(double v,int n) { double p; int i; if ( n == 0 ) { p = 1.0; } else { p = v; for ( i = 1 ; i <= n-1 ; i = i+1 ) { p = p*v; } } return p; } /* Calcul d'un polynome */ static double polynome(double x,int m,int n) { double res; res = puissance(x,m)+puissance(x,n); return res; } /* Programme principal */ public static void main(String [] args) { double x; int m; int n; double p; Ecran.afficher("SVP, x : "); x = Clavier.saisirDouble(); Ecran.afficher("SVP, m : "); m = Clavier.saisirInt(); Ecran.afficher("SVP, n : "); n = Clavier.saisirInt(); p = polynome(x,m,n); Ecran.afficherln("Resultat = ",p); } }
Polynome.java - Exemple d'exécution

Autres exemples

- Exemple 1
  - Une fonction surfaceCercle de calcul de la surface d'un cercle connu par son rayon (un réel en entrée en entête: le rayon, un réel retourné: la surface)
  - Une fonction main qui utilise la fonction surfaceCercle pour calculer et afficher la surface d'un cercle dont le rayon a été préalablement lu au clavier

public class SurfaceCercle { /* Calcul de la surface d'un cercle */ /* Le rayon r est donne */ static double surfaceCercle(double r) { double s; s = Math.PI*r*r; return s; } /* Programme principal */ public static void main(String [] args) { double rayon; double surface; Ecran.afficher("SVP, rayon : "); rayon = Clavier.saisirDouble(); surface = surfaceCercle(rayon); Ecran.afficherln("Surface = ",surface); } }
SurfaceCercle.java - Exemple d'exécution

- Exemple 2
  - Une fonction lectureEntierPositif de lecture au clavier d'un entier positif (essais successifs) (pas de paramètre d'entête, un entier retourné: la valeur lue)
  - Une fonction main qui utilise la fonction lectureEntierPositif pour lire au clavier et afficher un entier (simple validation du fonctionnement)

public class LectureEntierPositif { /* Lecture au clavier et retour d'un entier */ /* Saisie par essais successifs */ static int lectureEntierPositif() { int v; v = Clavier.saisirInt(); while ( v < 0 ) { Ecran.afficher("Erreur, resaisissez : "); v = Clavier.saisirInt(); } return v; } /* Programme principal */ public static void main(String [] args) { int n; Ecran.afficher("SVP, n : "); n = lectureEntierPositif(); Ecran.afficherln("Valeur lue = ",n); } }
LectureEntierPositif.java - Exemple d'exécution

- Exemple 3
  - Une fonction afficherEntiersPairs d'affichage de tous les entiers pairs entre 0 et une valeur limite (un entier en entrée en entête: la valeur limite, pas de valeur retournée),
  - Une fonction main de validation

public class AffichageEntiersPairs { /* Affichage de tous les entiers pairs entre 0 et n */ static void afficherEntiersPairs(int n) { int i; for ( i = 0 ; i <= n ; i = i+2 ) { Ecran.afficher(i," "); } } /* Programme principal */ public static void main(String [] args) { int n; Ecran.afficher("SVP, n : "); n = Clavier.saisirInt(); afficherEntiersPairs(n); Ecran.afficherln(); } }
AffichageEntiersPairs.java - Exemple d'exécution

Paramètres de type agrégé en entête de fonction Java?

- Comme pour les type prédéfinis, autorisation de passer des paramètres de type agrégé en entête de fonction

Exemple: Calcul du produit scalaire et calcul du produit vectoriel de deux directions 3D:

/* Type agrege de stockage d'une direction */ /* dans un espace trois dimensions */ /* a coordonnees reelles */ static class Direction3D { double x = 0.0; double y = 0.0; double z = 0.0; }; /* Calcul du produit scalaire de 2 Direction3D */ static double produitScalaire(Direction3D d1, Direction3D d2) { double res = d1.x*d2.x+d1.y*d2.y+d1.z*d2.z; return res; } /* Calcul du produit vectoriel */ /* de 2 Direction3D */ static Direction3D produitVectoriel(Direction3D d1, Direction3D d2) { Direction3D res = new Direction3D(); res.x = d1.y*d2.z-d1.z*d2.y; res.y = d1.z*d2.x-d1.x*d2.z; res.z = d1.x*d2.y-d1.y*d2.x; return res; } /* Programme principal */ public static void main(String [] args) { Direction3D d1 = new Direction3D(); Direction3D d2 = new Direction3D(); double ps; Direction3D pv; Ecran.afficherln("Veuillez saisir la premiere direction"); d1.x = Clavier.saisirDouble(); d1.y = Clavier.saisirDouble(); d1.z = Clavier.saisirDouble(); Ecran.afficherln("Veuillez saisir la seconde direction"); d2.x = Clavier.saisirDouble(); d2.y = Clavier.saisirDouble(); d2.z = Clavier.saisirDouble(); ps = produitScalaire(d1,d2); pv = produitVectoriel(d1,d2); Ecran.afficherln("Produit scalaire : ",ps); Ecran.afficherln("Produit vectoriel : ",pv.x,", ",pv.y,", ",pv.z); }
Produits3D.java - Exemple d'exécution

Cas particulier: Retour d'un paramètre de type agrégé par une fonction non void

- Obtention d'un retour qui peut être utilisé pour affectation à une variable, inclusion dans une expression, passage à une fonction, ...
- En cas d'affectation, utilisation sans problème de l'opérateur =
  -> Disparition de l'ancienne variable agrégée (à gauche du =) remplacée par le paramètre retourné par la fonction
  -> Pas nécessaire de faire un new dans le programme appelant car il est fait dans la fonction sur la variable retournée en fin de fonction

Passages de paramètres en entrée et en sortie en langage Javaa

- Quid des modes de passage de paramètre en entrée, en sortie et en entrée/sortie tels que définis en langage algorithmique?
- Fonctionnalité non implantée explicitement en langage Java
- Mode de passage défini implicitement par le type de paramètre

- En langage Java, mode de passage de paramètre pour les types byte, short, int, long, float, double, char, boolean et String (tous les types prédéfinis) implicitement et obligatoirement en entrée
- En langage Java, mode de passage de paramètre pour les types agrégés implicitement et obligatoirement en entrée/sortie
- En langage Java, pas de mode de passage de paramètre exclusivement en sortie

- Tous les types (prédéfini ou agrégé) supportent le mode de passage de paramètre en entrée
  -> Pas de problème pour la traduction langage algorithmique -> Java des passages de paramètre en entrée
- Seuls les types agrégés supportent le mode de passage de paramètre en sortie
  -> Problème pour la traduction langage algorithmique -> Java des passages en sortie des paramètres de type prédéfini

- Designs de programmation suivant le nombre de paramètres en sortie de type prédéfini:
  - Si 0 paramètre en sortie:
    - Une seule possibilité, une fonction void
  - Si 1 paramètre en sortie de type prédéfini A:
    - Une seule possibilité, une fonction non void avec retour d'un paramètre du type A
  - Si 2 ou plus paramètres en sortie de types prédéfinis:
    - Construction d'un type agrégé B permettant l'agrégation des paramètres en sortie en un seul paramètre agrégé
    - Deux possibilités:
      - Une fonction non void avec retour d'un paramètre de type B
      - Une fonction void avec un paramètre d'entête de type B (implicitement en entrée/sortie)

Exemple

- Développer un sous-algorithme ayant pour but de calculer un unique résultat: les coordonnées d'un point dans un espace à deux dimensions réelles
  (les données et le traitement ne sont pas ici précisés)
- En langage algorithmique, 3 possibilités:
  - Développement d'une action avec utilisation de deux paramètres d'entête de type réel nommés x et y passés en sortie
  - Création d'un type agrégeant deux champs de type réel nommés x et y
    Développement d'une action avec passage d'un paramètre d'entête de ce type passé en sortie
  - Création d'un type agrégeant deux champs de type réel nommés x et y
    Développement d'une fonction avec retour d'une valeur de ce type
- En langage Java, 2 possibilités:
  - Création d'un type agrégeant deux champs de type réel nommés x et y
    Développement d'une fonction void avec passage d'un paramètre d'entête de ce type (implicitement en entrée/sortie)
  - Création d'un type agrégeant deux champs de type réel nommés x et y
    Développement d'une fonction non void retournant comme résultat une valeur définie selon ce type

Application Java de calcul de l'intersection de deux droites du plan:

public class IntersectionDroites2D { /* Type agrege de stockage de coordonnees */ /* reelles en deux dimensions */ static class Coordonnees2D { double x = 0.0; double y = 0.0; }; /* Type agrege de stockage des composantes */ /* reelles d'une droite du plan */ static class Droite2D { double a = 0.0; double b = 0.0; }; /* Calcul de l'intersection entre deux droites */ /* d'équations y = a1*x+b1 et y = a2*x+b2 */ static Coordonnees2D intersection(Droite2D d1, Droite2D d2) { Coordonnees2D inter = new Coordonnees2D(); inter.x = (d2.b-d1.b)/(d1.a-d2.a); inter.y = d1.a*inter.x+d1.b; return inter; } /* Programme principal */ public static void main(String [] args) { Droite2D d1 = new Droite2D(); Droite2D d2 = new Droite2D(); Coordonnees2D inter; Ecran.afficher("SVP, coefficient directeur droite 1 : "); d1.a = Clavier.saisirDouble(); Ecran.afficher("SVP, ordonnée à l'origine droite 1 : "); d1.b = Clavier.saisirDouble(); Ecran.afficher("SVP, coefficient directeur droite 2 : "); d2.a = Clavier.saisirDouble(); Ecran.afficher("SVP, ordonnée à l'origine droite 2 : "); d2.b = Clavier.saisirDouble(); inter = intersection(d1,d2); Ecran.afficherln("Intersection : ( ",inter.x," , ",inter.y," )"); } }
IntersectionDroites2D.java - Exemple d'exécution

Recommandation

- Ecrire des sous-algorithmes courts (i.e. qui tiennent entièrement à l&-> Plus lisible
- Privilégier les sous-algorithmes avec résultat retourné (fonctions)
  -> Plus clair -> Plus clair
- Structurer les informations utilisées en passage de paramètre et en retour de sous-algorithme
  -> Plus clair et plus lisible