1. Le polymorphisme :
Le terme polymorphisme est certainement celui que l'on appréhende le plus. Mais il ne faut pas s'arrêter
à cela. Afin de mieux le cerner, il suffit d'analyser la structure du mot : poly comme plusieurs
et morphisme comme forme. Le polymorphisme traite de la capacité de l'objet à posséder plusieurs
formes.
Attention !
Le concept de polymorphisme ne doit pas être confondu avec celui d'héritage multiple. En effet,
l'héritage multiple - non supporté par le Pascal standard - permet à un objet d'hériter des membres
(champs et méthodes) de plusieurs objets à la fois, alors que le polymorphisme réside dans la capacité
d'un objet à modifier son comportement propre et celui de ses descendants au cours de l'exécution.
a. Règles de compilation
- Le compilateur connaît SEULEMENT le type de référence
- Peut seulement regarder dans la classe de référence pour la méthode
- Donne à la sortie la signature de la méthode
b. Règles d'exécution
- Suivez le type d'objet d'exécution exact pour trouver la méthode
- Doit faire correspondre la signature de la méthode de compilation à la méthode approprié
dans la classe de l'objet en cours
c. Casting
Casting est la conversion d'une expression d'un certain type en une expression d'un autre type.
Un opérateur cast est un opérateur unaire, qui a un seul opérande droit. La représentation physique de
l'opérateur cast est le nom d'un type à l'intérieur d'une paire de parenthèses correspondantes, comme dans:
(int)
Appliquer un opérateur de casting
L'application d'un opérateur de distribution au nom d'une variable ne change pas réellement le type de la
variable. Cependant, cela fait que le contenu de la variable est traité comme un type différent pour
l'évaluation de l'expression dans laquelle l'opérateur cast est contenu.
Passage automatique du type (comme int vers double)
• Superclass ref = new Subclass(); // Élargissement!
Explicit casting (comme double vers int)
• Subclass ref = (Subclass) superRef; // Rétrécissement!
FAITES ATTENTION:
Le compilateur vous fait confiance!
2. Classes et méthodes abstraites. Interfaces :
a. Java 8 et les interfaces
À partir de Java 8, on peut ajouter deux éléments supplémentaires dans une interfaces : des
méthodes statiques et des méthodes par défaut.
Méthode statique dans une interface
Une méthode statique est un élément que l'on peut rencontrer dans une classe normale. Un appel
statique se fait au travers de la classe, il n'a besoin d'aucune instance pour être exécuté. Java 8
autorise des méthodes statiques dans les interfaces, qui obésissent aux mêmes règles que celles que
l'on trouve dans les classes abstraites ou concrètes.
Exemple
public interface Function<T, R> {
R apply(T t) ;
static <T> Function<T, T> identity() {
return t -> t ; }}
Méthode par défaut
Du point de vue technique, une méthode par défaut ressemble à s'y méprendre à une méthode
concrète, écrite dans une interface.
Exemple
public interface List<T> {
default void sort(Comparator<t> comparator) {
Collections.sort(this, comparator) ; }}
Une méthode par défaut permet d'écrire une méthode dans une interface, en fixant sa signature et en
donnant une implémentation.
b. Utilité et utilisation des interfaces
Les interfaces ont été conçues pour traiter la problématique des propriétés transverses. Prenons deux
exemples, tirés de l'API standard du JDK.
L'interface Serializable est utilisée comme un tag. Cette interface ne comporte aucune méthode, sa
seule fonction est de marquer les classes qui pourront être "sérialisées", c'est-à-dire dont les instances
pourront être écrites dans des fichiers ou transmises via un réseau.
L'interface Comparable est ajoutée à certaines classes, comme les classes enveloppe des types de
base, ou la classe String. Elle indique que les instances de ces classes peuvent être comparées au sens
d'un algorithme fourni par l'implémentation. Donc, on peut ranger des instances de Comparable dans
des ensembles auto-ordonnés. Nous verrons un exemple précis lorsque nous présenterons
l'API Collection.
3. Packages. Exceptions:
a. Pakages (Variable CLASSPATH, classloader)
Les paquets sont utilisés en Java pour éviter les conflits de noms, pour contrôler l'accès, pour
faciliter la recherche / localisation et l'utilisation de classes, d'interfaces, d'énumérations et
d'annotations, etc.
Un package peut être défini comme un regroupement de types connexes (classes, interfaces,
énumérations et annotations) fournissant une protection d'accès et une gestion des espaces de
noms.
Classpath est un paramètre de la machine virtuelle Java ou du compilateur Java qui spécifie
l'emplacement des classes et des packages définis par l'utilisateur. Le paramètre peut être défini
sur la ligne de commande ou via une variable d'environnement.
La variable d'environnement nommée CLASSPATH peut également être utilisée pour définir le
chemin de classe. Pour l'exemple ci-dessus, nous pourrions également utiliser sur Windows:
set CLASSPATH = D: \ monprogramme
Le ClassLoader est la partie de la JVM qui charge les classes en mémoire.
Lorsque nous compilons une classe Java, elle la transforme sous la forme d'un bytecode qui est
un programme compilé indépendant de la plate-forme et de la machine et le stocke en tant que
fichier de classe. Après cela lorsque nous essayons d'utiliser une classe, Java ClassLoader charge
cette classe en mémoire.
Java ClassLoader est hiérarchique et chaque fois qu'une requête est lancée pour charger une
classe, elle la délègue à son parent et, de cette manière, l'unicité est maintenue dans
l'environnement d'exécution. Si le chargeur de classe parent ne trouve pas la classe, le chargeur
de classe lui-même essaie de charger la classe.
b. Exceptions (déclanchement et capture)
Une exception est un signal qui se déclenche en cas de problème. Les exceptions permettent de
gérer les cas d'erreur et de rétablir une situation stable (ce qui veut dire, dans certains cas, quitter
l'application proprement). La gestion des exceptions se décompose en deux phases :
La levée d'exceptions,
Le traitement d'exceptions.
En Java, une exception est représentée par une classe. Toutes les exceptions dérivent de la
classe Exception qui dérive de la classe Throwable
Le traitement des exceptions se fait à l'aide de la séquence d'instructions try...catch...finally.
L'instruction try indique qu'une instruction (ou plus généralement un bloc d'instructions)
susceptible de lever des exceptions débute.
L'instruction catch indique le traitement pour un type particulier d'exceptions. Il peut y avoir
plusieurs instructions catch pour une même instruction try.
L'instruction finally, qui est optionnelle, sert à définir un bloc de code à exécuter dans tous
les cas, exception levée ou non.
Il faut au moins une instruction catch ou finally pour chaque instruction try.
4. Type générique:
a. La programmation générique (classes et méthodes génériques)
Une classe qui peut faire référence à n'importe quel type est appelée classe générique. Nous
utilisons le paramètre de type T pour créer la classe générique de type spécifique.
Le type T indique qu'il peut faire référence à n'importe quel type (comme String, Integer,
Employee, etc.). Le type que vous spécifiez pour la classe sera utilisé pour stocker et
récupérer les données.
Ex:
class MyGen<T>{
T obj;
void add(T obj){this.obj=obj;}
T get(){return obj;}
}
Les méthodes génériques sont celles qui sont écrites avec une seule déclaration de méthode et
peuvent être appelées avec des arguments de types différents. Le compilateur assurera
l'exactitude de n'importe quel type est utilisé. Voici quelques propriétés des méthodes
génériques:
Les méthodes génériques ont un paramètre de type (l'opérateur du diamant englobant le type)
avant le type de retour de la déclaration de méthode
Les paramètres de type peuvent être bornés (les limites sont expliquées plus loin dans l'article)
Les méthodes génériques peuvent avoir différents paramètres de type séparés par des virgules
dans la signature de la méthode
Le corps de méthode pour une méthode générique est comme une méthode normale
b. Limites pour les variables de type, utilisation des sous-types et Type joker
ƒ Type joker permette de relâcher les contraintes sur les types paramétrés pour rendre des
méthodes plus réutilisables ƒ Faire une instanciation avec joker d’un type générique c’est donner
un type avec joker (« ? » est le joker) comme argument de type.
public static void paintAllBuildings(List<? extends Building> buildings) {
...}
Les caractères génériques sont représentés par le point d'interrogation dans Java "?" Et ils sont
utilisés pour désigner un type inconnu. Les caractères génériques sont particulièrement utiles lors
de l'utilisation de génériques et peuvent être utilisés en tant que type de paramètre, mais il y a
d'abord une note importante à prendre en compte
5. OOD et S.O.L.I.D. :
a. La méthode de conception OOD simplifiée ;
La méthode O.O.D (object oriented design) de G.Booch propose 5 étapes dans l’établissement d’une
conception orientée objet. Cette démarche se révèle être utile pour un débutant et lui permettra de
fabriquer en particulier des prototypes avec efficacité sans trop surcharger sa mémoire.
- Identifier les objets et leurs attributs :
On cherchera à identifier les objets du monde réel que l’on voudra réaliser.
On cherchera ensuite à identifier les actions que l’objet subit de la part de son environnement et qu’il
provoque sur son environnement.
- Etablir la visibilité :
L’objet étant maintenant identifié par ses caractéristiques et ses opérations, on définira ses relations
avec les autres objets.
- Etablir l’interface :
Dès que la visibilité est acquise, on définit l’interface précise de l’objet avec le monde extérieur.
- Implémenter les objets :
La dernière étape consiste à implanter les objets en écrivant le code.
Nous n’opposons pas cette méthode de conception à la méthode structurée par machines abstraites.
Nous la considérons plutôt comme complémentaire (en appliquant à des débutants une idée contenue
dans la méthode HOOD). La méthode structurée sert à faire élaborer par l’étudiant des algorithmes
classiques comme des actions sur des données. La COO permet de définir le monde de
l’environnement de façon modulaire. Nous réutiliserons les algorithmes construits dans des objets
afin de montrer la complémentarité des deux visions.
b. Les principes de conception S.O.L.I.D.
En programmation informatique, SOLID est un acronyme représentant cinq principes de bases pour
la programmation orientée objet, introduits par Michael Feathers et Robert C. Martin au début des
années 2000. Ils sont censés apporter une ligne directrice permettant le développement de logiciel
plus fiable et plus robust.
- Responsabilité unique (single responsibility principle) - une classe, une fonction ou une
méthode doit avoir une et une seule responsabilité
- Ouvert/fermé (open/closed principle) - une classe doit être ouverte à l'extension, mais fermée à
la modification
- Substitution de Liskov (Liskov substitution principle) - une instance de type T doit pouvoir
être remplacée par une instance de type G, tel que G sous-type de T, sans que cela ne modifie la
cohérence du programme
- Ségrégation des interfaces (en) (interface segregation principle) - préférer plusieurs interfaces
spécifiques pour chaque client plutôt qu'une seule interface générale
- Inversion des dépendances (dependency inversion principle) - il faut dépendre des
abstractions, pas des implémentations
l. Conception de l'architecture
n. Validation de l’architecture
8. Types d'architectures :
a. Concept
En informatique, architecture désigne la structure générale inhérente à un système informatique,
l'organisation des différents éléments du système
(logiciels et/ou matériels et/ou humains et/ou informations) et des relations entre les éléments. Cette
structure fait suite à un ensemble de décisions stratégiques prises durant la conception de tout ou partie du
système informatique, par l'exercice d'une discipline technique et industrielle du secteur de l'informatique
dénommée elle aussi architecture, et dont le responsable est l'architecte informatique.
La structure d'un système informatique n'est à ce jour assujettie à aucune norme. En matière de logiciels,
elle est représentée sous forme de graphiques tels que des organigrammes, des diagrammes
de workflow (flux de travaux en français) ou des diagrammes entité-relation. Le diagramme peut
concerner un logiciel, une pièce de matériel, un réseau informatique, un groupe de machines, un sous-
système, voire l'ensemble des dispositifs informatiques d'une entreprise ou d'une institution.
Un diagramme d'architecture est une perspective qui dépend du point de vue adopté par son auteur, en
fonction des éléments qu'il cherche à mettre en évidence. Le diagramme omet volontairement certains
détails pour rendre la perspective plus visible. Il peut y avoir plusieurs diagrammes d'architecture pour un
même système, tels que : architecture des informations, architecture métier, architecture applicative et
architecture technique
b. Mise en oeuvre
c. Style architectural
d. Style standards
Liste des questions pratiques pour l’examen final (problèmes sur les sujets) :
Le polymorphisme.
System.out.println("Constructing an Employee");
this.name = name;
this.address = address;
this.number = number;
return name;
return address;
address = newAddress;
}
public int getNumber() {
return number;
setSalary(salary);
return salary;
salary = newSalary;
return salary/52;
}
public class VirtualDemo {
s.mailCheck();
e.mailCheck();
#endregion
string Add ()
{
return "New person " + firstName + " " + lastName + " added.";
}
string Delete ()
{
return "Person" + firstName + " " + lastName + " deleted.";
#endregion
#endregion
}
Interfaces
interface Animal {
System.out.println("Mammal eats");
System.out.println("Mammal travels");
return 0;
}
public static void main(String args[]) {
m.eat();
m.travel();
Exceptions
this.number = number;
balance += amount;
balance -= amount;
}else {
return balance;
}
return number;
System.out.println("Depositing $500...");
c.deposit(500.00);
try {
System.out.println("\nWithdrawing $100...");
c.withdraw(100.00);
System.out.println("\nWithdrawing $600...");
c.withdraw(600.00);
} catch (InsufficientFundsException e) {
e.printStackTrace();
Type générique
private T t;
public T get() {
return t;
integerBox.add(new Integer(10));
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestJunit1.class ,TestJunit2.class
})
import org.junit.Test;
import org.junit.Ignore;
@Test
System.out.println("Inside testPrintMessage()");
assertEquals(message, messageUtil.printMessage());
import org.junit.Test;
import org.junit.Ignore;
System.out.println("Inside testSalutationMessage()");
assertEquals(message,messageUtil.salutationMessage());