280 likes | 396 Views
Surcharge d’opérateurs en Java. OO in J & ZKJC. Philippe Baqué Charles-Félix Chabert Christian Delbé Yannis Juan Encadré par Thomas Graf. Présentation du sujet. But : Permettre à l’utilisateur d’utiliser des opérateurs entre des types non-primitifs Sujet libre
E N D
Surcharge d’opérateurs en Java OOinJ & ZKJC Philippe Baqué Charles-Félix Chabert Christian Delbé Yannis Juan Encadré par Thomas Graf
Présentation du sujet • But : Permettre à l’utilisateur d’utiliser des opérateurs entre des types non-primitifs • Sujet libre • Pourquoi une spécification ? • Pourquoi une implémentation ?
Le plan • Travail de recherche • Spécification • Implémentation
Le travail de recherche • La surcharge dans les autres langages • Voir l’existant • En cerner les limites • Pouvoir s’en inspirer
Le travail de recherche • Explorer plusieurs routes avant de trouver son chemin … • Préprocesseur • Introduction d’un nouveau type
Préprocesseur Le travail de recherche • Approche simple et naturelle • a+best remplacé para.operator_plus(b) • Nécessité • d’une table de symbole • d’une résolution approriée • … Le préprocesseur devient un compilateur
Nouveau type Le travail de recherche • Nombreuses propositions (Gosling, Joy, Darcy,…) • Propositions très complètes … • … mais modifications importantes ! • Par exemple, modification de la Machine Virtuelle Java
La spécification • Points principaux • Proposer une extension de Java • Proposer une surcharge complète, mais simple • L’efficacité n’est pas le but !
Généralités La spécification • L’utilisateur • déclare des méthodes standards • utilise les opérateurs dans son code • L’extension • résout les occurrences d’opérateurs concernés • « passe la main » à Java
Les possibilités La spécification • Avec OOinJ, on peut écrire : OurInt o1 = (OurInt)1; OurInt o2 = (OurInt)2; OurInt [] oTab1 = {(OurInt)1, (OurInt)2}; int [] Tab2 = {3,4}; OurInt o3 = o1 + o2 * 2; OurInt [] oTab3 = oTab1 + Tab2;
Les opérateurs surchargeables La spécification • opérateurs unaires : +, -, ++, -- • opérateurs binaires : +, -, *, /, %, >, <, >=, <= • opérateurs d’affectation composés : +=, -=, *=, /=, %= • opérateur de conversion : (type)
Les opérateurs non surchargeables La spécification • Opérateur= • Opérateurs ==, != • Opérateurs||, && • Opérateur[]
Définir les opérateurs La spécification • Opérateurs unaires : operator:op(Type arg) • Opérateurs binaires : operator:op(Type1 arg1, Type2 arg2) • Opérateur de conversion : operator:(Type1)(Type2 arg) • Exemple : static OutInt operator:+(OurInt a, int b){ …}
Opérateurs : méthodes de classe La spécification • permettre l’écriture de a+1 et de 1+a • a+1 a.operator:+(1) • 1+a 1.operator:+(a) ??? A.operator:+(1,a) !!! • simplicité de la résolution • Méthode d ’instance : résolution sur le type dynamique • Méthode de classe : résolution sur le type statique
Localisation des opérateurs La spécification Au moins un des paramètres doit être : • du type de la classe qui déclare la méthode • ou un tableau dont le type terminal est letype de la classe qui déclare la méthode Maximum deux classes possible pour la résolution
Les opérateurs particuliers La spécification • Affectation composée : aop=b • Dérivé automatiquement deop a op=ba = a op b • Automatique : pourquoi ? • La surcharge de l’affectation n’est pas possible par l’utilisateur • Automatique : comment ? • Utilisation de l’opérateur simple correspondant, avec une restriction sur le type de retour. • Mécanisme d’évaluation particulier
Les opérateurs particuliers La spécification • Incrément (++) et décrément (--) : • Une seule méthode pour postfixe et préfixe • Exemple : • Méthode d’évaluation : • Résultat de l’expression a++ La référence de l’objet référencé par a • Résultat de l’expression ++a A.operator:++(a) • Dans les deux cas il y a affectation du résultat de A.operator:++(a) à la variable a public static OurInt operator:++(OurInt i){ return new OurInt(i.getValue()); }
Les opérateurs particuliers La spécification • Conversion : (Type)a • Beaucoup de restrictions Toutes les conversions autorisées en Java ne peuvent être redéfinies • Conversions explicites uniquement • Il est nécessaire de différencier les opérateurs de conversion explicite et les opérateurs de conversion implicite • La surcharge d’opérateurs de conversion implicite à un très grand impact sur Java • Possibilités de convertir des tableaux Les restrictions pour les conversions de tableau sont faites sur leur type terminal. Ces restrictions sont les même que pour des types non tableau
L’implémentation • Ne pas modifier KJC • Rester compatible avec les versions ultérieures • Etendre et non pas modifier Java • Compilation de tout programme Java standard • Interprétation par toute machine virtuelle • Respecter OOinJ
Phases de compilation L’implémentation Génération de code Phase 4 Vérification du corps Phase 3 Phase 2 Créer la représentation intermédiaire Phase 1 Analyse syntaxique
Analyse syntaxique L’implémentation • Accepter de nouvelles définitions : public static OurInt operator:+(OurInt a, OurInt b){ ... } étendre la grammaire de KJC
Représentation intermédiaire L’implémentation • Appeler notre vérification : • Soit on a une déclaration standard Traitement effectué par KJC : checkInterface(…) • Soit on a une déclaration étendue Traitement effectué par ZKJC : On redéfinit checkInterface(…)
Vérification du corps L’implémentation • Si on rencontre l’expression a + b • On rajoute une ZAddExpression dans l’arbre d’analyse ZAddExpression analyse JAddExpression analyse OK exception ZAddExpression tentative de résolution exception
Génération de code L’implémentation • Opérateurs d’affectation composés • extension des opérateurs binaires arithmétiques • Éviter la double évaluation OurInt T[]={(OurInt)1, (OurInt)2}; int i = 0; T[i++] += 1; Méthode + entre OurInt et int Vérification du type retour Affectation manuelle dans la pile
Génération de code L’implémentation • Opérateurs d’affectation composés • extension des opérateurs binaires arithmétiques • Éviter la double évaluation OurInt T[]={(OurInt)1, (OurInt)2}; int i = 0; T[i++] += 1; Méthode + entre OurInt et int Vérification du type retour Affectation manuelle dans la pile T[0] = T[0] + 1 i = 1
Génération de code L’implémentation • Incrément (++) et décrément (--) • une seule méthode déclarée • Impact sur la performance • génération de bytecode (duplication en pile) OurInt i = (OurInt) 1; i++; Méthode ++ appliquée à OurInt Postfixe ou préfixe ? Duplication de i en pile Appel de méthode
Génération de code L’implémentation • Incrément (++) et décrément (--) • une seule méthode déclarée • Impact sur la performance • génération de bytecode (duplication en pile) OurInt i = (OurInt) 1; i++; Méthode ++ appliquée à OurInt Postfixe ou préfixe ? Duplication de i en pile Appel de méthode 1 est renvoyé i = 2
Conclusion VIVE LES VACANCES