1 Introduction

publicité
Université Claude Bernard Lyon 1
ISFA
MASTER 2 – IR, 2015–2016
Remise à Niveau Java
TD1. Notions de bases
André FABBRI
Compétences indispensables à acquérir :
• Acquérir les notions de base du langage Java (classe/objet, héritage ...) ;
• Savoir mettre en place un projet Java sous NetBeans (création, paramètres).
1
Introduction
Java n’est pas seulement une île tropicale du Sud-Est asiatique mais correspond aussi
à un langage de programmation informatique. C’est à dire qu’il permet notamment
d’écrire certains des programmes informatiques que vous manipulez tous les jours sur
votre ordinateur. Pour ce faire, vous avez « simplement » à écrire dans un fichier source
(c’est à dire celui avec l’extension .java), un ensemble d’instructions rédigées suivant la
syntaxe du langage Java. Ce fichier sera ensuite compilé en Bytecode (c’est à dire des
fichiers avec l’extension .class). Les fichiers en Bytecode ne seront pas dépendant des
librairies d’exécution propre à la plateforme (Windows, Linux, Mac) sur laquelle vous
avez compilé, à la différence d’autres langages de programmation informatique (comme
le langage C). Les librairies nécessaires au programme seront chargées lors de son exécution par la JVM (Java Virtual Machine). En d’autres termes, votre programme sera
portable sur n’importe quelle plateforme pourvue que Java soit installé.
Figure 1 – Processus d’exécution d’un projet Java
Lors du lancement du programme, la méthode principale sera exécutée main. En Java,
elle doit disposer de l’entête suivante (dans des IDEs comme Netbeans, l’entête de cette
méthode est en général écrite automatiquement) :
public static void main[] (String args){ ... }
1
1.1
Exercice - Calcul de somme
Question 1 Ecrire le programme java Somme (classe Somme) qui permet de calculer
et d’afficher à l’écran la somme des 10 premiers entiers
Ce programme affichera à l’écran : « La somme des 10 premiers entiers est : 55 »
NB Création d’un projet NetBeans :
1. Fichier -> New Project ;
2. Sélectionner dans la catégorie Java un projet de type « Java Application » ;
3. Choisir le nom de la classe contenant le main afin de répondre à l’énoncé.
NB Affichage dans un terminal en Java : System.out.println("mon texte");
Question 2 Modifier ce programme pour que celui-ci puisse prendre en paramètre le
nombre d’entiers à sommer.
1. Modification de la fonction main :
Dans la fonction public static void main(String[] args), args[0] représente le premier paramètre passé au programme sous la forme d’une chaîne de
caractères (de type String).
NB Transformation d’une chaîne en entier :
int monEntier = Integer.parseInt(maChaîne); // par ex. maChaîne = «4»
2. Appeler la fonction main avec paramètre :
— depuis NetBeans (ou eclipse) : explorer les paramètres d’exécution du projet
(click droit sur le nom du projet depuis l’arborescence, puis sélectionner les
propriétés) ;
— en ligne de commande : trouver le répertoire contenant les classes compilées
(Bytecode), et exécuter : java monPackage.Somme 55
Question 3 (bonus) Modifier le programme de façon à ce que la somme soit désormais
celle de la série suivante : 1 + 1/2 + 1/3 + 1/4 + ... + 1/n. Veillez à limiter la perte
de précision (vous testerez avec des float pour n = 107 ).
2
2
Un langage orienté objet
Java est un langage orienté objet. En d’autres termes, les composantes du programme
sont décrites par des briques logicielles (appelés objets) qui sont définies arbitrairement
par le concepteur du programme. Un objet peut correspondre par exemple à un concept
comme une droite ou un point mais il peut aussi décrire des éléments du « monde
physique » comme un étudiant, une voiture.
En pratique, chaque objet créé par le programme est l’instance d’une classe définie
par le concepteur du programme. Une classe définit en quelque sorte les spécifications
des objets créés ; c’est à dire de quoi est composé un objet et comment il est possible
de l’utiliser. Une classe est composée d’un ensemble d’attributs (variables internes
propres à l’objet) et d’un ensemble de méthodes (fonctions spécifiques aux objets
de cette classe). Les attributs et les méthodes forment ce que l’on appelle les membres
de la classe. En UML, une classe se représente graphiquement de la manière suivante :
Figure 2 – Présentation graphique d’une classe
En Java, le code source associée à une classe doit être dans un fichier portant
le même nom ! Ainsi le code source associé à la classe présentée ci-dessus devra être
stocké dans un fichier appelé NomDeLaClasse.java. Il contiendrait alors les instructions
Java suivantes :
class NomDeLaClasse{
//attributs
private TypeA A_attributPrive;
public TypeB B_attributPublic;
protected TypeC C_attributProtege;
//methodes
public TypeMethodeD D_methodePublique() {
//code de la fonction
}
private TypeMethodeE E_methodePrivee() {}
protected TypeMethodeF F_methodeProtegee(){}
public TypeMethodeG G_avecParametres(Type1 param1,Type2 param2){}
};
3
2.1
Attributs d’une classe
En Java, les attributs d’une classe s’écrivent de la manière suivante :
(Visibilité) Type
Nom
(= valeur par défaut) ;
La visibilité : public, private, protected ou rien (cf. section 2.4) ;
Le type : de l’attribut comme float, String ou une classe déjà existante ;
Le nom : de l’attribut, c’est à dire comment il sera identifié dans votre code source.
Il est par ailleurs possible d’attribuer une valeur par défaut à un attribut lorsqu’un
objet est créé.
2.2
Méthodes d’une classe
En Java, les méthodes d’une classe s’écrivent de la manière suivante :
(Visibilité) Type de retour
Nom
( paramètres )
{ code }
La visibilité : public, private ou protected ou rien (cf. section 2.4) ;
Le type : de variable renvoyée à la fin de la fonction (instruction return) a ;
Le nom : pour appeler la fonction ;
Les paramètres : de la fonction sous la forme Type nom, ;
Le code de la fonction à exécuter lorsque celle-ci est appelée.
En mémoire, toute méthode est identifiée, de façon unique, par sa signature. La signature est la combinaison du Nom, des Paramètres (en particulier le type et l’ordre
de chacun des paramètres) et le Type de retour. Cela veut dire par exemple que deux
méthodes avec des noms et des types identiques mais des paramètres différents
seront différentes : on parle alors de surcharge de méthode.
a. Si aucune valeur est renvoyée, le mot clé void est nécessaire.
2.3
Constructeur d’une classe
Un constructeur est une méthode particulière d’une classe qui permet de créer
de nouvelles instances de cette classe : des objets. Il définit notamment le code à
exécuter lors de la création de l’objet (initialisation des attributs, éventuel affichage).
Un constructeur possède le même nom que la classe et ne possède pas de type de
retour. Il peut avoir cependant des paramètres pour initialiser les attributs de l’objet
par exemple. Une même classe peut avoir différents constructeurs avec des
paramètres différents (le constructeur sera alors surchargé). Par exemple pour la
classe précédente on peut avoir les constructeurs :
4
class NomDeLaClasse{
//attributs
private TypeA A_attributPrive;
//...
//methodes
public NomDeLaClasse() { A_attributPrive =0; }
public NomDeLaClasse(TypeA paramA) { A_attributPrive = paramA; }
};
En Java, l’appel du constructeur d’une classe est réalisé par l’opérateur new. Par
exemple pour créer un nouvel objet de type NomDeLaClasse, il suffit d’écrire :
NomDeLaClasse monObjet = new NomDeLaClasse(objetDuTypeA);
2.4
Accès aux membres d’un objet
Chaque objet mettra en oeuvre les spécifications correspondant à sa classe. En d’autres
termes, la création d’un nouvel objet implique : l’allocation en mémoire d’un espace
pour chacun des attributs et des références à chacune des méthodes de la classe. Pour
accéder aux membres d’un objet il est nécessaire d’utiliser l’opérateur
(« Point »).
Par exemple :
.
NomDeLaClasse monObjet = new NomDeLaClasse(); // Creation de l’objet
monObjet.B_attributPublic; // accès à l’attribut B_attributPublic
monObjet.D_methodePublique(); // appel de la méthode B_methodePublique()
La visibilité d’un membre définit le contexte depuis lequel il est possible d’accéder à celui-ci. Dans les langages orienté objet comme Java, il existe en général 3
niveaux de visibilité :
public : le membre est accessible depuis n’importe quel contexte (i.e. depuis n’importe quel fichier du projet) ;
private : le membre est accessible uniquement depuis des objets appartenant à
cette même classe (i.e. seulement depuis le fichier de la classe) ;
protected : il s’agit d’un niveau intermédiaire entre public et private que nous
reverrons plus longuement dans la section 3.1.
En Java, lorsque aucune visibilité n’est spécifiée dans la classe, le membre dispose par
défaut d’une visibilité package-private : le membre est accessible depuis des objets
appartenant au même package (i.e. seulement depuis des fichiers appartenant au
même sous-dossier que celui de la classe).
2.5
Exercice - Point, rectangle et cercle
Nous souhaitons créer un programme de géométrie euclidienne. Dans le cadre d’un
langage de programmation « orienté objet », nous aurons besoin de définir les classes
correspondant aux concepts comme un point, un rectangle et un cercle.
Question 1 Réalisez ce programme en suivant les spécifications ci-dessous et testez.
5
NB Organisation des fichiers dans NetBeans :
1. Créer un projet Geometrie : une classe Geometrie sera alors créée avec le main ;
2. Créer chacune des classes demandées dans un fichier différent. Vous testerez les
méthodes dans le programme principal.
Un Point a deux attributs publics correspondant à l’abscisse et à l’ordonnée du point.
En outre, les objets de la classe Point disposeront des deux méthodes suivantes :
• Un constructeur avec 2 paramètres pour initialiser l’abscisse et l’ordonnée ;
• Une méthode qui retourne un objet de type String avec l’abscisse et l’ordonnée.
Un Cercle a deux attributs publics : un Point correspondant au centre du cercle et un
entier correspondant au rayon. En outre, les objets de la classe Cercle disposeront des
deux méthodes suivantes :
• Un constructeur avec 2 paramètres pour initialiser le centre et le rayon ;
• Une méthode qui retourne un objet de type String avec le centre et le rayon.
Un Rectangle a six attributs publics : quatre attributs de type Point correspondant
aux quatre sommets du rectangle et deux attributs entiers correspondants à la longueur
et la largeur du rectangle. En outre, les objets de la classe Rectangle disposeront des
trois méthodes suivantes :
• Un constructeur avec comme paramètres deux Points. Ces points correspondront alors à deux des sommets du rectangle situés sur la même diagonale. Nous
supposerons ici que le rectangle formé par ces deux points sera systématiquement
le rectangle le plus simple qu’il est possible de construire (c’est à dire parallèle
aux axes). Vous déduirez dans le constructeur les deux autres sommets ainsi que
la longueur et la largeur du rectangle ;
• Une méthode qui renvoie le Point correspondant au barycentre du rectangle ;
• Une méthode qui retourne un objet de type String avec les principales informations du rectangle : longueur, largeur et le barycentre.
Question 2 Quel est le problème à déclarer les attributs de Rectangle en public ?
Modifiez en conséquence la classe Rectangle et ajouter des méthodes pour lire chacun
des champs.
De bonnes pratiques de programmation consistent à déclarer systématiquement
les attributs en private et de contrôler leurs accès en lecture et écriture au
travers de méthodes spécifiques appelées accesseurs. En général les méthodes pour
lire les attributs (appelés getter) sont de la forme :
public TypeAttribut getNomAttribut(){...}
et les méthodes pour modifier les attributs (appelés setter) sont de la forme :
public void SetNomAttribut(TypeAttribut nouvelleValeur){...}
Question 3 (bonus) Ajoutez des méthodes pour modifier les attributs de Rectangle
en assurant la cohérence entre tous les autres champs à chaque fois : c’est à vous de
préciser en commentaire vos choix pour l’ajustement.
6
3
Héritage de classe
La définition d’une classe doit parfois être réutilisée et complétée. La programmation
orienté objet dispose d’un puissant mécanisme à cet effet : l’héritage. Une classe fille
héritée d’une classe mère existante récupère l’ensemble des membres de la classe
existante, qu’il est ensuite possible de compléter par de nouveaux membres (attributs
ou méthodes). En Java la syntaxe est la suivante :
public class ClasseFille extends ClasseMere{
// code de la classe fille
};
La classe fille étend le type de la classe mère : il est possible de considérer un
objet de la classe fille comme étant aussi une instance de sa classe mère.
3.1
Accès aux membres de la classe mère
Une classe fille accède aux membres de sa classe mère comme n’importe quel autre objet.
Ainsi un objet de la classe fille ne pourra pas accéder aux membres hérités de sa classe
mère si ces derniers ont une visibilité private. C’est pour cette raison que la visibilité
protected a été introduite. Les membres de classe mère ayant une visibilité protected
sont accessibles depuis des objets de cette même classe (comme private) et des
objets appartenant à des classes héritées (classes filles). En Java, les membres ayant
une visibilité protected sont en plus accessible par toutes les classes appartenant au
même package (package-private).
3.2
Constructeur de la classe fille et méthodes héritées
La classe fille définit un nouveau type d’objet. Il est par conséquent nécessaire de définir
comment construire ces objets au travers d’un constructeur spécifique. Il est cependant
possible de faire appel au constructeur de la classe mère afin d’initialiser les attributs
hérités de cette classe par exemple. En Java, l’appel explicite d’une méthode de la
classe mère est réalisé avec le mot-clé super. Ainsi l’appel du constructeur de la classe
mère consiste à écrire super suivi des paramètres du constructeur entre parenthèses :
public class ClasseMere{
public ClasseMere(TypeA a, TypeB b){}
};
public class ClasseFille extends ClasseMere{
public ClasseFille(TypeA a, TypeB b){
super(a,b);
}
};
L’appel du constructeur de la classe mère doit impérativement être la première instruction du constructeur de la classe fille !
7
De manière générale, lorsque l’on souhaite appeler une méthode de la classe mère, il
suffit d’écrire super.nomMethodeClasseMere suivi des paramètres de la méthode entre
parenthèses :
public class ClasseMere
{
public TypeA methodeMere(TypeB param){...}
};
public class ClasseFille extends ClasseMere
{
public TypeC methodeFille(TypeB param)
{
// code
super.methodeMere(param);
}
};
Lorsqu’il n’y a aucune ambiguïté sur la méthode appelée, le mot-clé super n’est pas
nécessaire.
3.3
Surcharge et redéfinition
Dans la section 2.2, nous avions évoqué la possibilité de surcharger une méthode :
deux méthodes ayant le même nom, le même type de retour et les mêmes paramètres.
Dans une classe fille, il est possible de redéfinir une méthode de la classe mère. La
redéfinition d’une méthode d’une classe consiste à écrire, dans une classe héritée,
une méthode avec la même signature exactement : même nom, même type
de retour et mêmes paramètres.
3.4
Exercice - Point, rectangle et cercle (suite)
Nous souhaitons à présent généraliser les concepts de le rectangle et de cercle. Nous
introduisons un nouveau concept FigureUsuelle. La classe FigureUsuelle aura deux
attributs : le premier sera Point correspondant au barycentre de la figure et le second sera une couleur représentée par un objet de type String. Les objets de la classe
FigureUsuelle auront accès aux trois méthodes suivantes :
• Un constructeur par défaut avec aucun paramètre ;
• Un constructeur avec 2 paramètres pour initialiser les attributs ;
• Une méthode toString qui retourne un objet de type String intégrant ces deux
attributs.
Les classes Rectangle et Cercle hériteront de la classe FigureUsuelle et veilleront à
réutiliser au maximum les méthodes définies dans celles-ci.
Question 1 Modifiez le code du programme en conséquence : de nombreuses modifications sont à prévoir et attention aux visibilités.
8
Nous souhaitons à présent pouvoir calculer l’aire de chacune des figures usuelles créées.
Question 2 Ajoutez aux trois classes précédentes la méthode aire qui retourne l’aire
de la figure. On supposera que l’aire d’une FigureUsuelle est toujours égale à 0.
Question 3 Que peut-on dire des méthodes aire des classes Rectangle et Cercle ?
Question 4 Essayez les instructions ci-dessous ? Pouvez-vous expliquer pourquoi elles
fonctionnent ou pas ?
Rectangle rec= new Rectangle (...);
FigureUsuelle fig= new FigureUsuelle (...);
Rectangle rec2 = fig;
FigureUsuelle fig2= rec;
Question 5 Que retourne l’appel de toString sur rec et fig2 ? Qu’en déduisez
vous ? Quel intérêt voyez-vous à ce mécanisme ?
Le mécanisme d’héritage permet de définir des concepts de plus en plus abstraits à
tel point qu’il peut sembler aberrant de les instancier. De telles classes servent alors
essentiellement à factoriser des attributs ou des comportement communs. C’est pourquoi
il est possible de définir des classes abstraites. Une classe abstraite est une classe
qui ne peut pas être instanciée par un new. En Java, il suffit d’ajouter le mot-clé
abstract dans le nom de la classe. Attention, cela ne veut pas dire pour autant qu’une
classe abstraite n’a pas de constructeur !
Question 6
Quelle classe mériterait d’être abstraite en l’occurrence ?
Une méthode abstraite est une méthode dont il est nécessaire de redéfinir dans
chacune des classes filles. En java, il suffit d’ajouter le mot-clé abstract dans l’entête de la méthode et de retirer le code de la méthode de la classe mère : il ne reste
alors que la signature de la méthode. Seule une classe abstraite peut comporter
des méthodes abstraites. Les méthodes abstraites correspondent généralement à des
méthodes pour lesquelles il n’est pas possible ou souhaitable de les définir au niveau de
la classe mère.
Question 7
Quelle méthode mériterait d’être abstraite en l’occurrence ?
Question 8 (bonus) Allouez l’espace pour un tableau de 5 FigureUsuelle. Dans
chacune des cases stockez-y un Rectangle ou un Cercle. Calculez la somme des aires
de ces figures en parcourant chacune des cases du tableau. Que constatez-vous ?
9
Téléchargement