Si vos projets Java jusqu’à présent tenaient dans une seule classe, ces projets n’utilisaient pas le plein potentiel, ni même l’objectif, du langage Java. Ce langage a été développé quand l’Internet est devenu accessible au public pour créer des projets orientés-objet plus sécures et plus facilement distribuable que ce qui existaient déjà.
Mais pour des projets orienté-objet, il faut définir des objets, ce que vous n’avez pas fait intentionnellement jusqu’à présent.
Scanner input = new Scanner(System.in);
crée une instance de Scanner
nommée input
.main
pour la logique globale du programme. C’est la classe qui est lancée pour exécuter le programme. Elle crée et utilise des instances d’autres classes objets.new
new Scanner(System.in)
crée une instance de la classe Scanner
qui lit l’entrée standard.this
javac
javac *.java
compile tous les fichiers .java dans le dossier, générant les fichiers .class correspondants. On lance ensuite le programme avec java NomDeLaClassePilote
(sans l’extension .class ou .java).À la fin de cette leçon vous devrez être en mesure de :
new
et this
.Un projet orienté objet tient dans plusieurs classes - typiquement une classe par fichier, notamment :
main
pour la logique globale du programme -> on l’appelle la classe pilote. Voici quelques exemples de noms pour la classe pilote :
Les outils Java standard créent des structures de projets avec des dossiers pour les sources, les tests et les ressources. Les fichiers sources (comme le pilote et les objets) sont dans le dossier src
et les fichiers tests dans le dossier test
.
Pour le moment, nous créerons des projets simples sans structure spécifique : tous les fichiers .java seront dans le même dossier. La structure des fichiers pour un projet simple pourrait ressembler à ceci :
1
2
3
4
.
├── App.java
├── Person.java
└── TestPerson.java
Pour compiler ce projet, on ouvre le terminal dans le dossier racine du projet et on tape :
1
javac *.java
Ce qui ajoute les fichiers .class au dossier s’il n’y a pas d’erreurs de compilation. En cas d’erreurs de compilation, les messages d’erreur seront affichés à la console. Il faut faire cette étape de compilation à chaque modification du projet, sinon les fichiers .class utilisés pour lancer le programme ne seront pas à jour.
Finalement, pour lancer le programme, on tape :
1
java App
On ignore le fichier TestPerson.java ici parce que ce fichier est souvent généré et utilisé par des outils de test comme JUnit accessibles dans votre EDI. Pour plus d’information sur les tests unitaires, voir les notes du cours ICS3U
Un objet est une abstraction - un modèle informatique - pour quelque chose qui existe dans le monde réelle (ou dans notre imagination). Le modèle pour un objet est défini dans une classe qui contient des :
Voici quelques exemples d’objets qu’on utilise déjà :
String
: un modèle pour un texteScanner
: un modèle pour un lecteur de texteFile
: un modèle pour un élément du système de fichiers.Ces objets sont définies dans une classe du même nom dans les fichiers String.java
, Scanner.java
et File.java
à divers endroits dans la trousse de développement de Java (JDK).
Pour définir un objet, il suffit de créer une nouvelle classe dans un fichier .java du même nom, de déclarer ses attributs et de définir des méthodes.
Par exemple, dans Person.java :
1
2
3
4
5
6
7
8
9
10
class Person {
// attributs
String name;
int age;
// méthode
void speak() {
System.out.println(name + "dit 'Allô!'");
}
}
Notez qu’il n’y a pas de méthode main
dans cette classe, seulement les informations qui représentent notre modèle simple d’une personne (name
et age
) et d’un comportement associé (speak
).
Pour utiliser un objet, on déclare une variable du type de l’objet dans une méthode ou une classe. Chaque objet ainsi nommé s’appelle une instance de l’objet.
Exemple 1 : input
est une instance de Scanner
1
2
3
4
5
6
7
import java.util.Scanner;
class App {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
}
}
Exemple 2 : jenny
et andrew
sont des instances de Person
1
2
3
4
5
6
class Main {
public static void main(String[] args) {
Person jenny = new Person();
Person andrew = new Person();
}
}
jenny
a son propre bloc en mémoire pour name
et age
. De même, l’instance andrew
a son propre bloc en mémoire pour name
et age
.Pour utiliser les attributs et les méthodes d’une instance, on utilise l’opérateur .
après le nom de l’instance suivi par le nom de l’attribut ou de la méthode.
1
2
3
4
5
6
7
8
9
10
11
12
class Main {
public static void main(String[] args) {
Person jenny = new Person();
// Modifier les attributs
jenny.name = "Jenny";
jenny.age = 16;
// Utiliser les méthodes
jenny.speak();
// Afficher les attributs
System.out.println(jenny.name + " a " + jenny.age + " ans.");
}
}
Tentez de noter chaque fois que vous avez vu l’opérateur
.
dans les programmes que vous avez produits en ICS3U et en ICS4U jusqu’à présent (commeSystem.out.println()
). Chaque fois, c’était pour accéder à un attribut ou une méthode d’un objet.Par exemple,
System.out.println()
:out
est un attribut de typePrintStream
dans la classeSystem
, etprintln()
est une méthode de la classePrintStream
accessible par l’instanceout
.
this
Reprenons l’exemple de l’objet Person définit plus haut et ajoutons les méthodes changeName()
et happyBirthday()
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person {
String name;
int age;
void speak() {
System.out.println(name + "dit 'Allô!'");
}
void changeName(String name) {
this.name = name;
}
void happyBirthday(){
age += 1;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Main {
public static void main(String[] args) {
Person jenny = new Person();
jenny.name = "Jenny";
jenny.age = 16;
Person andrew = new Person();
andrew.name = "Andrew";
andrew.age = 17;
andrew.happyBirthday();
// andrew.age est maintenant 18
jenny.changeName("Jen");
// jenny.name est maintenant "Jen"
}
}
Le mot-clé this
dans les méthodes de la classe objet est utilisé pour faire référence à l’instance spécifique qui fait appel à la méthode.
Dans l’exemple ci-dessus, on le voit à un seul endroit, dans la méthode changeName()
. On utilise this.name
pour différencier la variable de l’instance name
de la variable locale name
passée en paramètre. Si vous copiez cette exemple dans votre IDE, en cliquant sur chaque name
dans la méthode changeName()
, vous verrez que celui précédé par this.
surligne également la déclaration de l’attribut name
de la classe tandis que l’autre surligne la déclaration du paramètre name
. Si vous enlevez le this.
, le compilateur ne saura pas quelle variable name
vous voulez modifier et vous donnera une erreur (surlignée en rouge).
Notez que dans les méthodes speak()
et happyBirthday()
, on n’a pas besoin de this.
parce qu’il n’y a pas de confusion possible. En l’absence de variables locales, les références à name
et age
peuvent seulement être celles de l’instance. Dans de tels cas, vous pouvez tout de même utiliser this.
pour plus de clarté, mais ce n’est pas nécessaire.
Quiz de vérification sur les objets
Produire une classe pilote et une classe qui définit un objet. Pour l’objet, modélisez quelque chose de votre vie qui existe en plusieurs instances. p. ex.: films, jeux, vélos, véhicules, artistes/athlètes/politiciens préférés, etc. Créer une ou deux instances de votre objet dans la méthode main()
du pilote, assigner des valeurs à chaque attribut et tester les différentes méthodes. Afficher les valeurs au besoin avec des System.out.println()
.
Plusieurs définitions de l’encapsulation incluent aussi l’idée de cacher les détails d’implémentation pour protéger les données, généralement en rendant les attributs privés et en fournissant une interface publique de méthodes pour les manipuler. Voir la leçon sur le masquage de l’information pour plus de détails. ↩
Dans les langages multi-paradigmes (comme Python) ou fonctionnelles (comme JavaScript, Rust), il y a d’autres façons d’encapsuler des données et des comportements à part les classes, notamment les fermetures / clôtures (closures en anglais). Par contre, la programmation orientée-objet utilise presque toujours les classes pour l’encapsulation. ↩