L'environnement se compose comme ceci :
1. Au centre se situe l'interface de développement : l'endroit où nous allons coder.
2. A gauche se trouve l'architecture du projet et l'ensemble des fichiers relatifs à ce projet.
3. En bas se situe la console. C'est l'endroit où nous voyons comment s'exécute notre programme
:
Le point d'entrée d'un programme JAVA est toujours la méthode main(). Cette méthode est définie par les
lignes suivantes :
public static void
main(
String[]
args){
...
}
Cette méthode se situe toujours dans une classe déclarée comme ceci :
public class
NomDeMaClasse {
...
}
Cet objet encapsule toutes les lignes de code du programme. La méthode main()
doit
absolument se
situer entre les accolades qui déterminent la classe.
Une ligne d'instruction se termine toujours par un ;
.
Le programme JAVA exécute toujours les lignes d'instructions de haut en bas. Il n'exécute que ce qui est
entre les accolades de la méthode main()
.
Dans le cas de notre exemple, la ligne d'instruction :
System.out.println("Hello World!");
permet d'afficher Hello World! dans la console (Outil vu précédemment).
Avant de démarrer le programme, il faut tout d'abord le compiler(*) à l'aide du bouton Build.
Pour démarrer notre programme, nous devons utiliser le bouton Run.
Un commentaire permet d'ajouter une information sur le programme.
C'est une ligne que nous écrivons
dans
le
programme mais qui n'est pas interprété lors de l'exécution de ce dernier.
Il existe plusieurs façons d'écrire un commentaire :
//pour commenter une simple ligne
/* pour commenter
* plusieurs
* lignes
*/
Un algorithme est une suite de lignes d'instructions. Un programme informatique est un gros algorithme.
Comme en mathématiques, pour fonctionner, un algortithme (informatique) ou un programme a besoin de variables.
Nous pouvons visualiser une variable comme un tiroir :
Il existe plusieurs types de variables que je vous invite à découvrir ci-contre :
/***************************************
* Déclaration de variables
****************************************/
//On précise d'abord le type puis le nom de la variable et enfin on affecte la valeur
//Il existe aussi le type short mais on l'utilise peu
int
variableDeTypeEntier = 6;
long
variableDeTypeEntierPlusLong = 6L; //Il est fortement conseillé de rajouter L derrière
afin de le différencier d'un int
double
variableDecimale = 6.3;
float
variableDecimaleDeTypeFloat = 6.3f; //Nous sommes obligés de rajouter un f derrière pour
signifier que ce n'est pas un double
//char signifie caractère. La valeur est à définir entre simple quote.
char
variableLettre = 'a';
//String signifie chaîne de caractères. La valeur est à définir entre double quotes
String
variableDeTypeTexte = "mon texte";
//boolean signifie une variable qui ne peut prendre que deux valeurs
//true signifie vrai
//false signifie faux
boolean
variableBoolean = true;
/*************************************************
* Modification de la valeur de variables existantes
*************************************************/
//nom de la variable = nouvelle valeur
//Il n'est pas nécessaire de définir à nouveau le type puisque cela a déjà été fait
variableDeTypeEntier = 8;
//Portion de code impossible. Un entier ne peut être affecté à une variable de type chaîne de
caractères
//variableDeTypeTexte = 9;
variableDeTypeTexte = "mon nouveau texte";
Les types de variables commençant par des minuscules sont des variables de type primitif. On ne peut leur appliquer de méthode. Elles ont juste une valeur.
Les variables dont les types commencent par des majuscules sont des variables de
type Objet. Des méthodes peuvent leur être appliquées. Par exemple :
Pour transformer une variable d'un certain type en un autre type, il faut la caster. En
d'autres termes, il faut forcer la variable à changer de type le temps de l'exécution de la
ligne. Pour rappel, nous avons dit dans le cours que lorsque le type d'une variable était
définie, nous ne pouvions pas la changer en cours de route. Voici l'exception qui confirme cette
règle.
Pour cela, il faut préciser lors de l'affectation à une autre variable le nouveau
type de la variable entre parenthèses.
Voici un exemple concret :
Parfois, il est nécessaire de stocker au "même endroit" plusieurs éléments.
Prenons l'exemple de notes. Pour chaque matière, nous avons une série de notes. Nous pouvons donc aisément imaginer stocker toutes les notes d'une même matière dans un tableau.
Le tableau pourrait ainsi prendre le nom de la matière et donner ceci :
french = [15, 16, 20, 12];
Si nous décomposons ce tableau, il s'agit de notes entières ou décimales.
Le problème c'est
qu'en JAVA, il est impossible de mettre des éléments de types différents dans un tableau. On
choisira donc un tableau de doubles puisque nous pouvons convertir facilement des entiers en
décimaux sans perdre d'informations alors que l'inverse n'est pas vrai.
Pour déclarer un tableau, plusieurs méthodes sont possibles :
int[]
french = {15, 16, 20, 12};
//Ceci est valable lorsque nous connaissons les notes à l'avance.
Si nous ne les connaissons pas, nous devons quand même connaître à l'avance le nombre de notes :
int[]
french =
new
int[4];
//Ceci est valable lorsque nous connaissons le nombre de notes à l'avance.
french[0] = 15;
//Les indices des tableaux commencent à 0.
french[1] = 16;
french[2] = 20;
french[3] = 12;
En résumé, la taille du tableau french
est bien de 4 mais le dernier indice est égal
à tailleDuTableau -1.
Les tableaux ont une réelle limite. Celle de la taille. Si le professeur de français décide de faire une interrogation surprise et rajoute une note, notre programme ne fonctionne plus. C'est pour cela qu'il existe les listes.
Comme les tableaux, on ne peut mettre qu'un type d'éléments dans une liste mais il est possible d'en ajouter, supprimer,... comme bon nous semble.
Pour cela :
ArrayList<Integer>
french =
new
ArrayList<>();
french.add(15);
french.add(16);
french.add(20);
french.add(12):
Comme pour les tableaux, les indices des listes commencent à 0.
INFORMATION IMPORTANTE, on ne peut stocker que des objets dans des ArrayList. Si vous souhaitez stocker des types primitifs, vous devez utiliser leur équivalent en Objet :
/*************************************
* TABLEAUX
************************************/
// Initialisation du tableau avec des données
int[]
monPremierTableau = {1, 2, 3, 4};
//Initialisation du tableau sans données
//Obligation de préciser la taille
int[]
monDeuxiemeTableau =
new
int[4];
//Ajout des données
//Les indices des tableaux et listes commencent à 0
//monDeuxiemeTableau[index] = valeur;
monDeuxiemeTableau[0] = 1;
monDeuxiemeTableau[1] = 2;
monDeuxiemeTableau[2] = 3;
monDeuxiemeTableau[3] = 4;
//Récupération d'une donnée
//Premier élément du tableau
System.out.println(monPremierTableau[0]);
//Dernier élément du tableau récupéré à l'aide de la taille
//monTableau.length
System.out.println(monDeuxiemeTableau[monDeuxiemeTableau.length-1]);
/*************************************
* LISTES
************************************/
//Seuls des objets peuvent remplir des listes
//Integer est l'objet correspondant à int
ArrayList<Integer>
maPremiereListe =
new
ArrayList<>();
//On oublie pas de l'initialiser sinon NPE
maPremiereListe.add(1);
maPremiereListe.add(2);
maPremiereListe.add(3);
maPremiereListe.add(4);
maPremiereListe.add(5);
//Déclaration de liste non instanciée, l'objet n'existe pas
//ArrayList<String> listeChaine = null;
//On ne peut donc pas ajouter de valeur dedans
//& on obtient l'erreur suivante : listeChaine est null
//java.lang.NullPointerException
//listeChaine.add("45");
//listeChaine.add("56");
System.out.println(maPremiereListe);
System.out.println(maPremiereListe.size());
//Affiche la taille de la liste
maPremiereListe.remove(1);
//Enlève l'élément "2" de la liste
System.out.println(maPremiereListe);
System.out.println(maPremiereListe.size());
Une méthode permet d'encapsuler une partie de code. Cela a plusieurs avantages :
Chaque méthode comporte un nom
. Ce nom doit être explicite !. Il
est donc interdit de les appeler a, methode ou autre.
Il faut voir une méthode comme un bloc de lignes de code. Ce bloc est donc encapsulé par des
{...}
précédées par le nom. En appelant dans la méthode main()
le nom de cette
méthode, le programme va lire toutes les lignes de code présentes dans la méthode puis revenir à la méthode
main()
.
En réalité, depuis le début, vous avez vu grand nombre de méthodes et notamment la fameuse :
public static void
main(String[] args) {...}
Cette méthode est la méthode principale, le point de départ du programme.
Pour faire les exercices, vous avez travaillé avec des méthodes. Celles-ci commencent toujours par les mots clefs suivants :
public static
: ceci indique que tout le programme peut utiliser la méthode (Nous rentrerons dans les détails plus
tard.)
void
,
String
ou autre : ce que retourne la méthode.
void
signifie que la méthode ne retourne rien. Elle se contente d'exécuter des lignes de code sans rien
retourner à la méthode principale. Ce que fait cette méthode ne sera pas "exploitable" par le programme
par la suite.nomDeLaMéthode()
: le nom utilisé pour l'appeler dans le programme. En CamelCase (*)paramètres
: ce sont des variables que nous passons à la méthode pour
que cette dernière puisse l'utiliser.
public static void
main(){
// Méthode principale d'un programme JAVA
System.out.println("Cette méthode est déroulée automatiquement dès qu'on lance le
programme.");
//Appel d'une autre méthode par le biais de son nom
methodeSansParametre();
//Je stocke ce qui est retourné par la méthode dans une variable afin de le réutiliser
String chaineRenvoyee = methodeSansParametreQuiRenvoieUneString();
//J'utilise le résultat retournée par methodeSansParametreQuiRenvoieUneString() pour
l'afficher dans la console
System.out.println(chaineRenvoyee);
//Je créé une variable de type int correspondant à mon âge
int
monAge = 27;
//J'appelle la méthode methodeAvecUnParametre et je mets entre les parenthèses la variable qui
se nomme monAge
methodeAvecUnParametre(monAge);
//Je peux aussi l'appeler en passant une valeur directement
methodeAvecUnParametre(30);
//J'appelle methodeAvecPlusieursParametres et je mets directement les valeurs
//Attention : ici, il est attendu en premier une chaine de caractères et en second un entier
//Veillez à mettre les éléments dans cet ordre sinon à la compilation, vous obtiendrez une
erreur
methodeAvecPlusieursParametres("Marie", 27);
//CODE GENERANT UNE ERREUR
//methodeAvecPlusieursParametres(27, "Marie");
//J'appelle methodeAvecPlusieursParametres
//Non mais comment ça, elle existe déjà mais on met une chaine de caractères & un entier
normalement
//Oui mais nous en avons créé une seconde qui attend deux entiers
//C'est comme cela que JAVA saura laquelle appeler. Grâce au type !
int
monAgeCalcule = methodeAvecPlusieursParametres(20,7);
System.out.println("Mon âge calculé : "+monAgeCalcule + " ans");
}
public static void
methodeSansParametre() {
System.out.println("Je suis une méthode sans paramètre et qui ne revoie rien à la méthode qui
l'a appelée.");
}
public static String
methodeSansParametreQuiRenvoieUneString() {
System.out.println("Je suis une méthode sans paramètre et qui renvoie une chaîne de caractères
à la méthode qui l'a appelée.");
String resultat = "La chaîne que methodeSansParametre() renvoie";
//J'utilise le mot clef return pour retourner la chaîne de caractères à la méthode qui l'a
appelée
return
resultat;
}
public static void
methodeAvecUnParametre(
int
age) {
System.out.println("J'affiche l'âge passé en paramètre de la fonction "+ age);
}
public static void
methodeAvecPlusieursParametres(
String
prenom,
int
age) {
System.out.println("Je m'appelle "+ prenom + " et j'ai "+age +" ans.");
}
public static int
methodeAvecPlusieursParametres(
int
nb1,
int
nb2) {
//On additionne nb1 et nb2
int
resultat = nb1 + nb2;
//J'utilise le mot clef return afin de retourner le résultat à la méthode qui l'a appelée
return
resultat;
}
/***********************************************************************************
* CODE IMPOSSIBLE : Nous pouvons créer deux méthodes portant le même nom
* mais il ne faut pas qu'elles aient le même nombre et le même type de paramètres
* sinon "JAVA ne saura pas dans quelle méthode aller"
************************************************************************************/
/* public static int methodeAvecPlusieursParametres(int nb1, int nb2) {
int resultat = nb1 * (int) nb2;
return resultat;
}*/
Ces structures permettent au programme de prendre des décisions. Si certaines conditions sont remplies alors le programme exécutera telle ligne de code plutôt qu'une autre.
Vous vous souvenez des booléens ? C'est ici qu'ils interviennent. Si ce qu'on demande au
programme est vrai alors la condition est remplie sinon elle n'est pas remplie. Voici un exemple
concret.
Est-ce que Pauline est majeure ?
Vous ne savez pas son âge à cet instant
mais vous pouvez traduire cette condition par ageDePauline >= 18
.
Plus
tard, dans votre programme, vous apprenez que Pauline a deux ans. La condition devient alors
ageDePauline >= 18
devient 2 >= 18 ?
Nous sommes bien d'accord le résultat est faux et traduit en booléen false
. La
condition n'est donc pas remplie.
Pas de problème ! Nous avons le &&
(et) et le ||
(ou) pour combiner
plusieurs conditions.
|
|
En anglais if... else if... else
.
/*************************************************
* IF
*************************************************/
//Une condition
int
ageDePauline = 2;
if
(ageDePauline >= 18){
System.out.println("La condition est remplie");
}
else
{
System.out.println("La condition n'est pas remplie");
}
if
(ageDePauline >= 0 && ageDePauline < 2){
System.out.println("C'est un bébé");
}
else if
(ageDePauline <= 2 && ageDePauline < 19){
System.out.println("C'est une enfant.");
}
else
{
System.out.println("C'est un adulte");
}
//Combinaison de plusieurs conditions
if
(ageDePauline >= 2 && ageDePauline <= 18){
System.out.println("Ce n'est plus un bébé et ce n'est pas un adulte non plus. Les
deux conditions sont remplies.");
}
if
(ageDePauline > 2 && ageDePauline <= 18){
System.out.println("Loupé... si on utilise && (et). Si l'une des conditions n'est
pas remplie alors l'ensemble des conditions sera faux.");
}
else
{
System.out.println("Pauline n'a pas un âge strictement supérieur à deux ans
(conditions non remplies) et elle est bien mineur (condition remplie)");
}
if
(ageDePauline > 2 || ageDePauline <= 18){
System.out.println("Bien joué... si on utilise || (ou). Si l'une des conditions est
remplie alors l'ensemble des condition sera vrai.");
}
else
{
System.out.println("Pauline n'a pas un âge strictement supérieur à deux ans
(conditions non remplies) mais elle est bien mineur (condition remplie)");
}
if...else
. Elle va plus vite à
écrire mais est plus difficile à lire.
/*******************************************************
* TERNAIRE
* résultat = condition ? condition vérifiée : condition non vérifiée;
*******************************************************/
int
age = 20;
//Le résultat de la variable isMajeur dépend de la condition
//age >= 18 ?
//Si oui, isMajeur = true
//Sinon, isMajeur = false
String
isMajeur = age >= 18 ? "Il est majeur" : "Il est mineur";
/* EQUIVALENT
String isMajeur1;
if(age >= 18){
isMajeur1 = "Il est majeur";
}
else{
isMajeur1 = "Il est mineur";
}*/
System.out.println("majeur si âge = 20 ? " + isMajeur);
age = 15;
isMajeur = age >= 18 ? "true" : "false";
System.out.println("majeur si âge = 15 ? " + isMajeur);
switch(condition) case...
.
/*******************************************************
* SWITCH CASE
*******************************************************/
//Date du jour
LocalDate
date = LocalDate.now();
//Jour en français
String
dayInFrench = date.format(DateTimeFormatter.ofPattern("EEEE", Locale.FRANCE));
System.out.println(dayInFrench);
switch
(dayInFrench){
case
"lundi" :
System.out.println("pfffff le début de semaine, duuuur.");
break
;
case
"mardi" :
System.out.println("en cours...");
break
;
case
"jeudi" :
System.out.println("dire qu'avant, on sortait en soirée étudiante le jeudi.");
break
;
case
"samedi":
case
"dimanche":
System.out.println("C'est le week-end !");
break
;
default
:
System.out.println("En cours... mais par défaut !");
}
/*******************************************************
* SWITCH CASE
* DEPUIS JAVA 12 mais je suis en JAVA 11
*******************************************************/
/*switch(dayInFrench){
case "lundi" -> System.out.println("pfffff le début de semaine, duuuur.");
case "mardi" -> System.out.println("en cours...");
case "jeudi" -> System.out.println("dire qu'avant, on sortait en soirée
étudiante le jeudi.");
case "samedi", "dimanche" -> System.out.println("C'est le week-end !");
default -> System.out.println("En cours... mais par défaut !");
}*/
Ces structures permettent au programme de parcourir un tableau, une liste ou encore de répéter une opération un certain nombre de fois. Le programme arrête alors l'exécution de cette boucle de différentes manières :
i
),En programmation, nous avons le choix entre plusieurs boucles. Pour ma part, je préfère les boucles
for
(pour). Nous avons moins de risques de tomber dans une boucle infinie et ainsi faire
planter le programme. Nous terminerons donc par celles-ci. Avant cela, les boucles tant que et
faire tant que.
En anglais while
.
Ici, tant que la condition est vérifiée (tant que la valeur passée entre parenthèses renvoie
true
), le programme exécute les instructions placées entre les accolades.
Si la condition n'est pas vérifiée, le programme ne passe pas du tout dans les accolades.
int
condition = 15;
/************************************************
* TANT QUE
************************************************/
int
j = 13;
while
(j > condition){
System.out.println("On ne passe jamais dans la boucle puisque la condition n'est pas
vérifiée.");
}
j = 18;
while
(j > condition){
System.out.println("On passe dans la boucle puisque la condition est vérifiée.");
//On décrémente j pour que la condition ne soit plus vérifiée.
j--;
//j = j-1;
System.out.println(j);
//Lorsque j atteindra 15, la condition ne sera plus vérifiée. On sortira de la boucle.
}
En anglais do... while
.
Ici, le programme exécute au moins une fois ce qu'il y a entre les accolades. Arrivé à la fin, il
continue d'exécuter ce qu'il y a entre les accolades tant que la condition est vérifiée (tant que la
valeur passée entre parenthèses renvoie true
).
/************************************************
* FAIRE TANT QUE
************************************************/
j = 13;
do
{
System.out.println("Avec le do...while, on passe une fois dans la boucle même si la
condition n'est pas vérifiée.");
}
while
(j > condition);
j = 18;
do
{
System.out.println("On passe dans la boucle une première fois et après aussi puisque la
condition est encore vérifiée.");
//On décrémente j pour que la condition ne soit plus vérifiée.
j--;
//j = j-1;
System.out.println(j);
//Lorsque j atteindra 15, la condition ne sera plus vérifiée. On sortira de la boucle.
}
while
(j > condition);
for...
.x fois
où x
est
préalablement défini.
/************************************************
* POUR
************************************************/
//Pour un index nommé i ALLANT de 0 A 5 non compris (puisque <) PAR PAS DE 1 (i++)
for
(int i = 0; i < 5; i++){
System.out.println("Boucle for : "+i);
}
//Avec un tableau ou une liste
int[]
tab = {1,2,3,4,5,6,7};
ArrayList<Double>
list = new ArrayList<>();
list.add(1.1);
list.add(2.2);
list.add(3.3);
for
(int k=0; k < tab.length; k++){
int
el = tab[k];
System.out.println("Boucle for avec tableau : "+ el);
}
for
(
int
l=0; l < list.size(); l++){
Double
el = list.get(l);
System.out.println("Boucle for avec liste : "+ el);
}
for
dans le code.tab[index]
ou list.get(index)
.
/************************************************
* POUR CHAQUE ELEMENT
************************************************/
//for TYPE des éléments dans le tableau/liste NOMVARIABLE : ELEMENT_PARCOURU
for
(
int
elementTab : tab){
//foreach($tab as $elementTab)
System.out.println("Boucle foreach avec tableau : "+ elementTab);
}
for
(
Double
elementList : list){
System.out.println("Boucle foreach avec liste : "+ elementList);
}
break
permet de quitter la boucle.
/************************************************
* BREAK
************************************************/
for
(
int
k=0; k < tab.length; k++){
if
(k == 2){
break
;
}
int
el = tab[k];
System.out.println("On affiche l'élément parce que la condition k == 2 n'est pas
vérifiée : "+ el);
}
System.out.println("Dès que k==2, on sort de la boucle. Les autres éléments du tableau ne seront
pas traités.");
continue
permet de passer à l'itération d'après
sans exécuter le code qui suit.
/************************************************
* CONTINUE
************************************************/
for
(
int
k=0; k < tab.length; k++){
if
(k == 2){
System.out.println("Puisque k==2, on ne va pas afficher la phrase habituelle avec la
valeur. On passe notre tour : on \"continue\".");
System.out.println("ATTENTION");
System.out.println("Pour rappel, les indices des tableaux et listes commencent à 0 et nos
valeurs à 1. C'est pour cela que nous avons un \"décalage\".");
continue
;
}
int
el = tab[k];
System.out.println("On affiche l'élément parce que la condition k == 2 n'est pas vérifiée :
"+ el);
}
for each
.
Qu'affiche cet algorithme ? Il affiche 1.
int
n = 50;
for
(
int
i = 1; i < n; i++){
if
(i%2 == 0) {
continue ;
}
if (i%3 == 0){
break ;
}
System.out.print(i);
}
Revenons sur le langage JAVA. Créé par Sun en 1995 puis racheté par Oracle en 2009. JAVA 15 depuis septembre 2020 mais non LTS (*). C'est pour cela qu'en cours, nous utilisons JAVA 11, qui lui est LTS et plus stable.
Lors de la création du langage Java, il avait été décidé que ce langage devait répondre à cinq objectifs :
La programmation orientée objet (P.O.O) est une programmation basée sur des objets qui possèdent des attributs et des méthodes. Cela permet d’avoir une programmation proche de la réalité.
En P.O.O, nous pourrions utiliser un objet de type ordinateur pour créer :
De même, l'objet Ordinateur est lui-même composé de plusieurs objets :
En programmation orientée objet, c'est pareil !
La P.O.O tourne autour des objets. Chaque objet est unique et défini par :
Concrètement, une classe est un moule pour représenter des objets qui ont des caractéristiques communes.
Exemple : Ordinateur est le "moule" pour créer un Mac Pro, un Mac, un Asus Chromebook,...
Ce sont ces caractéristiques que nous représentons en UML :
UML généré via IntelliJ qui correspond à la classe Student.java dont le lien est ci-dessous
Code source de la classe Student.java
Un diagramme de classes permet aussi et surtout de décrire l'ensemble des classes d'un programme comme le diagramme ci-dessous qui représente le cours :
Code source de la classe Address.java
Une méthode dite statique est une méthode qui est indépendante d’un objet. La méthode getCurrentYear()
ne se rapporte à aucun objet précisément puisqu'elle relate l'année en cours. Nous pouvons donc le
mettre statique dans une classe que l'on nommera Time
.
public class
Time {
public static int
getCurrentYear(){
LocalDate
today = LocalDate.now();
return
today.getYear();
}
}
Pour l'utiliser, rien de plus simple : NomDeLaClasse.nomMethode()
Pour utiliser une méthode se rapportant à un objet (non statique),
nomObjet.nomMethode();
//Création d'un objet
Student
adrien =
new
Student("NOM", "Adrien");
//Appel d'une méthode non statique
//se référant à l'objet adrien de type Student
System.out.println(adrien.getFirstname());
//Pour appeler une méthode statique qui se situe dans une autre classe
//NomDeLaClasse.methode()
System.out.println(Time.getCurrentYear());
//Pour appeler une méthode static qui se situe dans la même classe
//le nom de la méthode suffit
System.out.println(getMethodStaticInSameClass());
Pour créer un objet (instance), il faut utiliser le constructeur. & pour l'appeler, nous
devons utiliser le mot clef new
.
Ici, vous pouvez voir :
Address ad = new Address();
new
CONSTRUCTEUR;Ici, c'est le contsructeur vide qui est appelé.
Dans le second cas, celui de Student
, c'est le second constructeur qui est appelé. Celui
avec les paramètres. Attention, un constructeur est une méthode particulière, nous devons donc
(comme pour les méthodes) passer les arguments dans le bon ordre.
Student student = new Student(1L, "GUYOTON", "Marie", date, ad);
où
1L
est la valeur donnée pour l'attribut id
"GUYOTON"
est la valeur donnée pour l'attribut lastname
"Marie"
est la valeur donnée pour l'attribut firstname
date
est la valeur donnée pour l'attribut birthdate
(date est bien un
objet)
ad
(objet créé précédement) est la valeur donnée pour l'attribut
address
//Création d'un Student adrien
Student
adrien =
new
Student("NOM", "Adrien");
//Création d'un Student leo avec un autre constructeur
Student
leo =
new
Student(2L, "DUPONT");
System.out.println(adrien.getFirstname());
//NPE : NullPointerException
//On essaie d'accéder à un attribut d'un objet qui n'existe pas
System.out.println(adrien.getAddress().getPostalCode());
//Ajout d'une adresse dans l'attribut address d'adrien
adrien.setAddress(address);
//Cela fonctionne puisque l'attribut address d'adrien n'est plus null
System.out.println(adrien.getAddress().getPostalCode());
Une énumération est un type d'objets avec un nombre d'instances déterminées. Il est impossible de créer un nouvel objet de ce type là. Les attributs (s'il y a) sont aussi définis dès le départ. Il est impossible d'utiliser les setters pour les modifier.
Deux façons de les créer :
public enum
Role {
ADMIN, USER;
}
//enum & non class
public enum
Days {
//INSTANCES toujours déclarées en MAJUSCULES
MONDAY(1, "lundi"),
TUESDAY(2, "mardi"),
WEDNESDAY(3, "mercredi"),
THURSDAY(4, "jeudi"),
FRIDAY(5, "vendredi"),
SATURDAY(6, "samedi"),
SUNDAY(7, "dimanche");
//final pcq une fois la valeur affectée à l'attribut
//elle ne change jamais
private final int
nbDay;
private final String
dayInFrench;
/*Pas de public devant le constructeur
pcq on ne peut pas créer d'objet Days
*/
Days(
int
nbDay,
String
dayInFrench) {
this .nbDay = nbDay;
this .dayInFrench = dayInFrench;
}
/*Pas de setters*/
public int
getNbDay() {
return this .nbDay;
}
public String
getDayInFrench() {
return this .dayInFrench;
}
}
L'encapsulation est un des grands principes de la programmation orientée objets. Le principe est simple : tous les attributs sont privés et nous créons des getters et setters SI BESOIN !
Cela permet aux développeurs d'éviter de fausses manipulations comme changer un id en base de données. Cela peut aussi éviter des injections de code dans des attributs non utilisés...
L'encapsulation passe par la portée des attributs et méthodes. Il en existe 4 :
public
: tout le projet a accès à l'attribut/méthode,
private
: seule la classe en elle-même a accès à la méthode ou à l'attribut,
package
(par défaut - aucun mot clef nécessaire lors de la déclaration) : seules
les
classes dans le même package ("répertoire") ont accès aux méthodes et aux attributs définis
comme
ceci,
protected
: seules les classes dans le même package ainsi que les classes filles ont accès aux
méthodes et
aux attributs.
Voici un exemple concret : (Cliquez sur le nom des classes pour accéder au code)
L'héritage "génétique", c'est avoir sa propre personnalité, ses propres membres et pourtant, on hérite d'une partie de la personnalité de nos parents, de certaines caractéristiques (les yeux...). Qu'on le veuille ou non, cela nous "suit".
En programmation, c'est pareil. Une classe fille hérite de tous les attributs de la mère (sous réserve que les getters et setters soient publics) ainsi que des méthodes.
extends
.
Ici, la classe Fille (Renegade)
hérite de la classe mère Voiture qui hérite elle-même de la classe ObjetDeLocomotion.
public class Renegade extends Voiture...
super()
. Cf. Renegade.java.
Voici un exemple concret : (Cliquez sur le nom des classes pour accéder au code)
Le polymorphisme commence par le biais d’une interface abstraite. Une interface (abstraite) est une "classe" où des méthodes sont définies mais non implémentées. Cela permet des les implémenter différemment en fonction des objets auxquelles elles s’appliquent.
Par exemple, prenons l'interface objetDeLocomotion. Dans celle ci est déclarée la méthode
avancer()
.
Si nous créons trois objets voiture, train et avion, nous pouvons tous les implémenter de notre
classe
objetDeLocomotion car ils sont tous des
objets de locomotion. Ils avancent donc tous.
Nous devons donc à présent implémenter la méthode avancer()
. Or, celle-ci ne sera pas la
même si l’objet de locomotion est une voiture,
un train ou un avion.
// Les interfaces sont souvent nommés avec un "I" devant pour les différencier des classes
//Aujourd'hui, les IDE utilisent des logos différents afin de mieux le faire
public interface
IObjetDeLocomotion {
//Méthode déclarée mais non implémentée
public void
avancer();
public void
stop();
}
Pour cela, nous allons utiliser le mot clef implements
. L'avantage de cette solution par
rapport à l'héritage, c'est que nous pouvons implémenter plusieurs classes.
public class
Avion
implements
IObjetDeLocomotion, IDeuxiemeInterface {
//On définit le comportement des méthodes présentes dans IObjetDeLocomotion
@Override
public void
avancer() {
System.out.println("Un avion vole pour avancer.");
}
@Override
public void
stop() {
System.out.println("stop");
}
//Méthode qui provient de IDeuxiemeInterface
@Override
public void
ok() {
System.out.println("ok avion");
}
}
Nous pouvons aussi utiliser ce concept avec l'héritage mais ce n'est pas son but premier. Pour cela,
il
suffit d’ajouter des méthodes abstraites dans la classe mère ou éventuellement des méthodes
classiques
dont on redéfinit le comportement dans les classes filles. Il faut pour cela rajouter un
@Override
devant la méthode en question.
public abstract class
ObjetDeLocomotion {
private String
name;
//...
public
ObjetDeLocomotion(
String
pName){
this
.name = pName;
}
//Méthode pouvant être redéfinie dans les classes filles
//Avec un comportement par défaut
public String
rouler(){
return
"rouler";
}
//Méthode abstraite à définir absolument dans les classes filles
//Pas d'implémentation définie
public abstract void
test();
}
public class
Avion
extends
ObjetDeLocomotion
implements
IObjetDeLocomotion, IDeuxiemeInterface {
public
Avion(
String
pName) {
super
(pName);
}
//Vu précédemment, implémentation des méthodes provenant des interfaces
[...]
//On redéfinit le comportement de la méthode rouler qui se trouve
// dans ObjetDeLocomotion
@Override
public String
rouler(){
return
"un avion roule juste pour décoller";
}
//On redéfinit la méthode abstraite héritée de ObjetDeLocomotion
@Override
public void
test() {
System.out.println("test avion");
}
}
Voici un exemple concret : (Cliquez sur le nom des classes pour accéder au code)