ublicrivateackagemportxtendsbstract
Plan
.6@percent
-
Sous-typage et héritage
- Héritage et Surcharge
- Classes abstraites et interfaces de Java
- Initialisation des classes
- Racine de la hiérarchie des classes
- Réflexivité
- Polymorphisme en Java
- Interfaces graphiques
- Entrée graphique
- Exemples d'utilisation d'AWT
Sous-classes « sous-typage (1/2)
-
Notation:
signifie que la variable Java x est de type t.
signifie x:t Þ x:t' pour tout x.
(conversion implicite)
On dit que t est un sous-type de t'.
- En Java,
byte <:
short <:
int <:
long float <: double char <: int |
C <: C' si C est une sous-classe de C'. |
Par exemple PointC
<: Point
.
- Posons
t ® t' pour le type des fonctions de t dans t', |
t × t' pour le type du produit cartésien de t et t'. |
- Alors
t <: t' et u <: u' |
Þ |
t' ® u <: t
® u' |
t <: t' et u <: u' |
Þ |
t × u <: t' × u'. |
(<: contravariant à gauche et covariant à droite de ®)
Sous-classes « sous-typage (2/2)
-
Exemple de dérivations de types:
rotation:
Point
× double
® Point
PointC
<: Point
PointC
× double
<: Point
× double
Point
× double
® Point
<:
PointC
× double
® Point
rotation:
PointC
× double
® Point
mais on ne peut pas dériver:
rotation:
PointC
× double
® PointC
Exercice 1 Donner la loi de sous-typage pour les tableaux.
Théorie plus compliquée en présence de polymorphisme ou de
méthodes binaires
Þ sous-classe ne correspond plus
à la notion de sous-typage.
Þ Ocaml, GJ (Generic Java = Java 1.5), Generic C#
La théorie des types est introduite dans le cours Principes des
Langages de Programmation de Majeure 1. Cf. livre de
Benjamin Pierce ou de
Abadi-Cardelli.
Notation objet et héritage
C est une classe et o un objet de
cette classe (o : C)
|
statique |
dynamique |
variable |
C.x |
o.x |
fonction |
C.f() |
o.f() |
En terminologie objet, fonction = méthode.
Exemples quand on déclare String s,t;
et
Point p;
function |
System.in |
p.x |
|
Point.rotation(p) |
s.equals(t) |
- o.f(...) est l'application de la méthode la
plus spécialisée s'appliquant à o.
- C'est l'application de f tel que
o : C |
f méthode de C |
C minimum pour <: |
Dans l'évaluation de f, alors this
vaudra o.
Exercice 2 Expliquer la notation System.out.println
.
Héritage et surcharge (1/3)
- la surcharge est déterminée à la compilation
- l'héritage est dynamique;
la méthode est sélectionnée à l'exécution
- l'héritage permet d'appeler une méthode sans savoir exactement
quelle sous-classe va l'instancier (liaison tardive);
objets = monde ouvert
Exercice 3 Quelle est la valeur imprimée par le programme suivant?
class C {
void f() { g(); }
void g() { System.out.println(1); }
} }
class D extends C {
void g() { System.out.println(2); }
public static void main (String[ ] args) {
D x = new D();
x.f();
} } Exécution
Héritage et surcharge (2/3)
Exercice 4 Quel est le résultat produit par le programme suivant quand
T,T' Î {A, B} et U,U' Î {A, B} avec T' <: T et U' <:
U ?
public static void main (String[ ] args) {
T x = new T'(); U y = new U'();
System.out.println (x.f(y));
}
int f (A y) {return 1; }
}
class B extends A {
int f (B y) {return 2; }
} Exécution
Héritage et surcharge (3/3)
Classes abstraites -- Interfaces (1/2)
-
·Une classe abstraite contient des champs indéfinis.
- ·Þ on ne peut créer que des objets de classes non abstraites.
- Un interface est une classe abstraite dont tous les
champs sont indéfinis.
Ses champs de données sont constants;
ses méthodes sont abstraites et publiques.
- Un interface peut spécialiser un autre interface.
- Une classe peut implémenter un ou plusieurs interfaces
Þ Héritage multiple pour les interfaces.
- Notion différente des interfaces de Modula, ML, Ada, Mesa. En
Java, la classe qui les implémente porte un nom différent.
- Pas de fonctions statiques, ou champs de données modifiables
dans un interface.
- Les interfaces sont une bonne manière d'exiger la présence de certains
champs dans une classe.
mplements
Classes abstraites -- Interfaces (2/2)
public interface Couleur {
final int ROUGE = 0, JAUNE = 1;
}
interface PointCirculaire {
void static rotation (Point p, double theta);
}
interface PointMobile {
void static translation (Point p, double dx, double dy);
}
class Point implements PointCirculaire, PointMobile {
...
}
Exercice 5 Quel type utilise-t-on pour référencer les objets d'une
classe implémentant un interface?
Exercice 6 Même question à l'intérieur de la classe implémentant
l'interface?
Initialisation des classes
Le mot-clé static
suivi d'un bloc d'instructions permet de
faire une initialisation de la classe à son chargement (lors du premier accès à un de ses champs).
class Point {
double x, y;
static void translation (Point p, double dx, double dy) {
p.x = p.x + dx; p.y = p.y + dy;
}
static Point rotation (Point p, double theta) {
double x = p.x * Math.cos(theta) - p.y * Math.sin(theta);
double y = p.x * Math.sin(theta) + p.y * Math.cos(theta);
return new Point(x, y);
}
static {
System.out.println ("La classe Point vient d'être chargée");
}
}
Racine de la hiérarchie des classes
Object
est la classe la plus générale:
(C est une classe ou un tableau quelconque).
Réflexivité
Polymorphisme (1/3)
Pas de polymorphisme en Java (avant 1.5). Pour l'approximer, on
peut tenter de se servir de la classe Object
.
class Liste {
Object valeur; Liste suivant;
static int length (Liste x) {
if (x == null) return 0;
else return 1 + length (x.suivant);
}
static Liste append (Liste x, Liste y) {
if (x == null) return y;
else return new Liste(x.valeur, append(x.suivant, y));
}
}
Marche pour length
, mais pas pour append
où
on doit faire des conversions explicites.
Polymorphisme (2/3)
ou en style orienté-objet.
abstract class Liste {
abstract int length () ;
abstract Liste append (Liste y);
}
class Nil extends Liste {
int length () { return 0; }
Liste append (Liste y) { return y; }
}
class Cons extends Liste {
Object valeur; Liste suivant;
static int length () { return 1 + suivant.length(); }
static Liste append (Liste y) {
return new Cons(valeur, suivant.append(y));
}
}
Exercice 7 Comment calculer la longueur d'une liste d'entiers à partir
de la fonction précédente.
Polymorphisme (3/3)
Procédural ou Objets?
(bis)
-
choix du contrôle:
par les fonctions ou par les données?
- le style de programmation diffère entre petits programmes et
gros programmes (> 104 lignes).
- dépend de la stratégie de modification.
- en dernière analyse: affaire de goût.
- objets ¹ modularité.
- programmation par objets utilisée dans:
-
·les boîtes à outils graphiques (look commun à toutes les fenêtres)
- ·réseau (données et méthodes se déplacent
simultanément).
- programmation incrémentale très populaire dans
l'industrie.
Paquetages et Classes graphiques
On utilisera (au choix) 3 bibliothèques graphiques:
-
MacLib, plus simple, locale à l'X. Pour trouver la
documentation consulter le lien suivant
http://www.enseignement.polytechnique.fr/profs/informatique/Philippe.Chassignet/MACLIB/Java/maclib_java.html
- AWT (Abstract Window Toolkit) de Sun Microsystems, dans la version 1.1.
Orienté-objet.
Compatible avec les classes des appliquettes applet, exécutables sous
un navigateur.
- Swing de Sun Microsystems, pour les versions plus récentes de JDK. Avec
une boîte à outils plus garnie.
MacLib (1/2)
Initialement compatible avec QuickDraw du MacInstosh.
class Lissajoux {
static final double X0 = 100, Y0 = 100, K = 80, A = 3, B = 2, D = 0.9;
static int X(double t) { return (int) (X0 + K*Math.cos(A*t)); }
static int Y(double t) { return (int) (Y0 + K*Math.sin(B*t+D)); }
public static void main(String[ ] args) {
final int N = 120;
double t = 0;
MacLib.initQuickDraw(); // initialisation du graphique
MacLib.moveTo(X(0), Y(0));
for (int i = 0; i < N; ++i) {
t = t + 2 * Math.PI/N;
MacLib.lineTo(X(t), Y(t));
} } } Exécution
Merci à Philippe Chassignet (LIX).
MacLib (2/2)
Ou avec la notation objets:
class Lissajoux {
static final double X0 = 100, Y0 = 100, K = 80, A = 3, B = 2, D = 0.9;
static int X(double t) { return (int) (X0 + K*Math.cos(A*t)); }
static int Y(double t) { return (int) (Y0 + K*Math.sin(B*t+D)); }
public static void main(String[ ] args) {
final int N = 120;
double t = 0;
GrafPort g = new GrafPort("mon dessin");
g.moveTo(X(0), Y(0));
for (int i = 0; i < N; ++i) {
t = t + 2 * Math.PI/N;
g.lineTo(X(t), Y(t));
} } }
Permet d'avoir plusieurs GrafPort
.
Entrée graphique (1/3)
Front descendant
(ne pas oublier d'attendre
le front montant)
|
|
Front montant (plus sûr) |
|
|
for(;;) {
while (!g.button())
;
Point p = g.getMouse ();
while (g.button())
;
action (p.h, p.v);
} |
|
for (;;) {
while (!g.button())
;
while (g.button())
;
Point p = g.getMouse ();
action (p.h, p.v);
} |
Attente active (busy wait).
Entrée graphique (2/3)
- in.read() est blocant
Þ problème pour lire simultanément le clavier et la souris.
- problème de la séquentialité. Il faut
gérer l'asynchronie.
- ·solution 1: avoir un read non blocant
- ·solution 2: faire des processus et gérer le parallélisme
asynchrone.
- ·solution 3: avoir une structure d'événements gérés par le
système. Par exemple le pilote (driver) d'événements de X-window.
- ·solutions plus sophistiquées
- callbacks dans la programmation par objets
- langages spécialisés pour gérer modulairement les
interactions: Squeak [Cardelli-Pike]; Esterel
[Berry- ···]
cas particulier des systèmes réactifs.
- pour double-click, il faut estampiller les événements par le temps.
Entrée graphique (3/3)
Librairie AWT
Un interface utilisateur graphique (GUI) est formé de:
-
composants (component): boutons, canevas, checkbox, choix, container, étiquette, liste de textes, barre
de déroulement, texte, etc.
- conteneurs (container): listes de composants, affichés de
devant vers l'arrière. Plusieurs types de conteneurs: les
panneaux, les appliquettes, les zones de déroulement, les fenêtres ou les
cadres (frames), ...
- détecteurs (listeners) d'événements attachés à des
composants par la méthode
addXXXListener
.
On spécialise les méthodes dans ces détecteurs pour engendrer des actions
spécifiques.
- Modèle/Présentation/Contrôle
(MVC) sont séparés (comme en Smalltalk).
awt
Fenêtre graphique
import java.awt.*;
class Frame1 {
public static void main (String[ ] args) {
Frame f = new Frame ("Bonjour");
f.add ("Center", new Label ("Bonjour les élèves!", Label.CENTER));
f.setSize (300, 100);
f.setVisible(true);
} } Exécution
ou en programmation par objets:
class Frame2 extends Frame {
Frame2 (String s) {
super(s);
add ("Center", new Label ("Bonjour les élèves!", Label.CENTER));
setSize (300, 400);
setVisible(true);
}
public static void main (String[ ] args) {
Frame2 f = new Frame2 ("Bonjour");
} } Exécution
Contexte graphique
class Frame3 extends Frame {
Frame3 (String s) {
super(s);
add ("North", new Label ("Bonjour les élèves!", Label.CENTER));
setSize (300, 400);
setVisible(true);
}
public static void main (String[ ] args) {
Frame3 f = new Frame3 ("Frame2");
}
public void paint (Graphics g) {
int w = getSize().width;
int h = getSize().height;
int x = w/2; int y = h/2;
g.setColor(Color.red);
g.fillRect(x-w/4, y-w/4, w/4, w/2);
g.setColor(Color.yellow);
g.fillRect(x, y-w/4, w/4, w/2);
}
} Exécution
Les méthodes paint
et repaint
affichent les composants.
Un bouton avec interaction
import java.awt.*;
import java.awt.event.*;
public class Frame4 extends Frame {
Button q = new Button ("Quit");
public Frame4 (String title) {
super (title);
setLayout (new FlowLayout());
add(q);
setSize (300, 100);
q.addActionListener (new Quit());
setVisible(true);
}
public static void main (String[ ] args) {
Frame4 f = new Frame4 (args[0]);
} }
class Quit implements ActionListener {
public void actionPerformed (ActionEvent e) {
System.exit(0);
} } Exécution
Deux boutons et un texte
public class Frame5 extends Frame {
Button q = new Button ("Quit");
Button a = new Button ("A");
TextField t = new TextField (20);
public Frame5 (String title) {
super (title); setLayout (new FlowLayout());
add(q); add(a); add(t);
setSize (300, 100);
q.addActionListener (new Quit());
a.addActionListener (new ActionA(t, "Bouton a!"));
setVisible(true);
}
...
} }
class ActionA implements ActionListener {
TextField t; String s;
ActionA (TextField t0, String s0) { t = t0; s = s0; }
public void actionPerformed (ActionEvent e) {
t.setText(s);
} } Exécution
Une interaction à la souris
public class Frame6 extends Frame {
public Frame6 (String title) {
super (title);
setLayout (new FlowLayout());
add(q); add(a); add(t);
validate();
pack();
addMouseListener (new ActionB(t, "Bouton relache'."));
q.addActionListener (new Quit());
a.addActionListener (new ActionA(t, "Bouton a!"));
setVisible(true);
}
...
}
class ActionB extends MouseAdapter {
TextField t; String s;
ActionB (TextField t0, String s0) {t = t0; s = s0; }
public void mouseReleased (MouseEvent e) {
t.setText(s);
} Exécution
Evénements souris
-
événements souris: bouton enfoncé, bouton relaché, souris déplacée, souris déplacée bouton enfoncé
(drag), souris entrant sur un composant, souris sortant
d'un composant.
- un détecteur d'événements-souris
MouseListener
est
un interface contenant 5 méthodes mousePressed
,
mouseReleased
,
mouseClicked
,
mouseEntered
, mouseExited
.
- un
MouseAdapter
est une implémentation de
l'interface précédent avec les 5 méthodes vides. Ainsi on ne
définit que les méthodes à spécifier.
- les méthodes
getX()
, getY()
, getPoint()
retournent les coordonnées de l'événement.
Exercice 8 Programmer un petit interface utilisateur où on imprime
les coordonnées du point courant sur un clic souris.
Exercice 9 Programmer un petit interface utilisateur qui dessine
un vecteur entre deux points rentrés à la souris.
This document was translated from LATEX by
HEVEA.