Surcharge d’opérateurs en Java Philippe Baqué Charles-Félix Chabert Christian Delbé Yannis Juan Encadré par Thomas Graf OOinJ & ZKJC
Jan 03, 2016
Surcharge d’opérateurs en Java
Philippe Baqué Charles-Félix ChabertChristian Delbé Yannis Juan
Encadré par Thomas Graf
OOinJ & ZKJC
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
Approche simple et naturelle a+b est remplacé par a.operator_plus(b)
Nécessité d’une table de symbole d’une résolution approriée …
Le préprocesseur devient un compilateur
Le travail de recherche
Nouveau type
Nombreuses propositions (Gosling, Joy, Darcy,…)
Propositions très complètes …
… mais modifications importantes ! Par exemple, modification de la Machine
Virtuelle Java
Le travail de recherche
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
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
La spécification
Les possibilités
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;
La spécification
Les opérateurs surchargeables
opérateurs unaires :
+, -, ++, -- opérateurs binaires :
+, -, *, /, %, >, <, >=, <= opérateurs d’affectation composés :
+=, -=, *=, /=, %= opérateur de conversion :
(type)
La spécification
Les opérateurs non surchargeables
Opérateur =
Opérateurs ==, !=
Opérateurs ||, &&
Opérateur []
La spécification
Définir les opérateurs
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){
…}
La spécification
Opérateurs : méthodes de classe
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
La spécification
Localisation des opérateurs
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 le type de la classe qui déclare la méthode
Maximum deux classes possible pour la résolution
La spécification
Les opérateurs particuliers
Affectation composée : a op=b Dérivé automatiquement de op
a op=b a = 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
La spécification
Les opérateurs particuliers
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
La spécification
public static OurInt operator:++(OurInt i){
return new OurInt(i.getValue());
}
Les opérateurs particuliers
Conversion : (Type)a
Beaucoup de restrictionsToutes 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
La spécification
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
Phase 1
Phase 2
Phase 3
Phase 4
Analyse syntaxiqueAnalyse
syntaxique
Créer la représentation intermédiaire
Créer la représentation intermédiaire
Vérification du corps
Vérification du corps
Génération de code
Génération de code
L’implémentation
Analyse syntaxique
Accepter de nouvelles définitions :
public static OurInt operator:+(OurInt a, OurInt b){
...
}
étendre la grammaire de KJC
L’implémentation
Représentation intermédiaire
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(…)
L’implémentation
Vérification du corps
Si on rencontre l’expression a + b On rajoute une ZAddExpression dans l’arbre d’analyse
ZAddExpressionanalyse
JAddExpressionanalyse
ZAddExpressiontentative de résolution exception
OK
L’implémentation
exception
Génération de code
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;
L’implémentation
Méthode + entre OurInt et int
Vérification du type retour
Affectation manuelle dans la pile
Génération de code
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;
L’implémentation
T[0] = T[0] + 1 i = 1
Méthode + entre OurInt et int
Vérification du type retour
Affectation manuelle dans la pile
Génération de code
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 à OurIntPostfixe ou préfixe ?
Duplication de i en pileAppel de méthode
L’implémentation
Génération de code
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 à OurIntPostfixe ou préfixe ?
Duplication de i en pileAppel de méthode
1 est renvoyé
i = 2
L’implémentation
Conclusion
VIVE LES VACANCES