|
La suite traite du concept d'héritage et de sa mise en oeuvre en Java.
|
|
La suite traite du concept d'héritage et de sa mise en oeuvre en Java.
|
|
|
|
|
|
- [Relation d'héritage](#relation-d-h-ritage)
|
|
# Table des matières
|
|
- [Mise en place de l'héritage : le mot-clé `extends`](#mise-en-place-de-l-h-ritage---le-mot-cl---extends-)
|
|
|
|
- [Visibilité des éléments hérités](#visibilit--des--l-ments-h-rit-s)
|
|
<!-- TOC start (generated with https://github.com/derlin/bitdowntoc) -->
|
|
|
|
|
|
|
|
- [Relation d'héritage](#relation-dhéritage)
|
|
|
|
- [Mise en place de l'héritage : le mot-clé `extends`](#mise-en-place-de-lhéritage-le-mot-clé-extends)
|
|
|
|
- [Visibilité des éléments hérités](#visibilité-des-éléments-hérités)
|
|
- [Constructeurs de la sous-classe](#constructeurs-de-la-sous-classe)
|
|
- [Constructeurs de la sous-classe](#constructeurs-de-la-sous-classe)
|
|
- [Redéfinition de méthode](#red-finition-de-m-thode)
|
|
- [Redéfinition de méthode](#redéfinition-de-méthode)
|
|
- [Liaison tardive (*lookup*)](#liaison-tardive---lookup--)
|
|
- [Liaison tardive (*lookup*)](#liaison-tardive-lookup)
|
|
- [Retour sur le polymorphisme ](#retour-sur-le-polymorphisme)
|
|
- [Retour sur le polymorphisme ](#retour-sur-le-polymorphisme)
|
|
- [Classe `Object`](#classe--object-)
|
|
- [Classe `Object`](#classe-object)
|
|
* [Méthode `equals`](#m-thode--equals-)
|
|
* [Méthode `equals`](#méthode-equals)
|
|
* [Méthode `hashCode`](#m-thode--hashcode-)
|
|
* [Méthode `hashCode`](#méthode-hashcode)
|
|
* [Méthode `toString`](#m-thode--tostring-)
|
|
* [Méthode `toString`](#méthode-tostring)
|
|
- [Retour sur les énumérations](#retour-sur-les--num-rations)
|
|
- [Retour sur les énumérations](#retour-sur-les-énumérations)
|
|
|
|
|
|
<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>
|
|
<!-- TOC end -->
|
|
|
|
|
|
|
|
<!-- TOC --><a name="relation-dhéritage"></a>
|
|
# Relation d'héritage
|
|
# Relation d'héritage
|
|
|
|
|
|
:book: L'**héritage** est un des mécanismes orientés-objet fondamentaux, qui consiste à **s'appuyer sur des classes déja écrites** en les **réutilisant** pour modéliser des **concepts plus spécifiques** de la manière la plus concise et rapide possible.
|
|
:book: L'**héritage** est un des mécanismes orientés-objet fondamentaux, qui consiste à **s'appuyer sur des classes déja écrites** en les **réutilisant** pour modéliser des **concepts plus spécifiques** de la manière la plus concise et rapide possible.
|
... | @@ -53,6 +58,7 @@ L'héritage peut être replacé dans le contexte des autres relations fortes , |
... | @@ -53,6 +58,7 @@ L'héritage peut être replacé dans le contexte des autres relations fortes , |
|
|
|
|
|
:rocket: Dans d'autre langages orientés objets, comme par exemple C++ ou Python, l'héritage multiple est autorisé. Par exemple, on pourrait définir la classe `ImprimanteScanner` par héritage à la fois des classes `Imprimante`et `Scanner`.
|
|
:rocket: Dans d'autre langages orientés objets, comme par exemple C++ ou Python, l'héritage multiple est autorisé. Par exemple, on pourrait définir la classe `ImprimanteScanner` par héritage à la fois des classes `Imprimante`et `Scanner`.
|
|
|
|
|
|
|
|
<!-- TOC --><a name="mise-en-place-de-lhéritage-le-mot-clé-extends"></a>
|
|
# Mise en place de l'héritage : le mot-clé `extends`
|
|
# Mise en place de l'héritage : le mot-clé `extends`
|
|
|
|
|
|
:book: La relation sous-classe/super-classe s'exprime via le mot-clé `extends`.
|
|
:book: La relation sous-classe/super-classe s'exprime via le mot-clé `extends`.
|
... | @@ -86,6 +92,7 @@ Spécifiquement, la classe `Worker`: |
... | @@ -86,6 +92,7 @@ Spécifiquement, la classe `Worker`: |
|
- définit des accesseurs en lecture pour ces nouveaux attributs
|
|
- définit des accesseurs en lecture pour ces nouveaux attributs
|
|
- redéfinit le comportement de la méthode `exportVCard` qui génère une carte de visite "professionnelle" alors que le comportement décrit dans la classe `Person` consistait à générer une carte de visite "personnelle".
|
|
- redéfinit le comportement de la méthode `exportVCard` qui génère une carte de visite "professionnelle" alors que le comportement décrit dans la classe `Person` consistait à générer une carte de visite "personnelle".
|
|
|
|
|
|
|
|
<!-- TOC --><a name="visibilité-des-éléments-hérités"></a>
|
|
# Visibilité des éléments hérités
|
|
# Visibilité des éléments hérités
|
|
|
|
|
|
:book: Bien que les attributs et méthodes soient héritées, ces éléments ne sont pas obligatoirement visibles et par conséquent manipulables depuis les sous-classes. Cela dépend de la visibilité qui leur a été donnée dans la super-classe :
|
|
:book: Bien que les attributs et méthodes soient héritées, ces éléments ne sont pas obligatoirement visibles et par conséquent manipulables depuis les sous-classes. Cela dépend de la visibilité qui leur a été donnée dans la super-classe :
|
... | @@ -102,6 +109,7 @@ Spécifiquement, la classe `Worker`: |
... | @@ -102,6 +109,7 @@ Spécifiquement, la classe `Worker`: |
|
|
|
|
|
:book: Lorsque des attributs ou méthodes hérités sont visibles, ils peuvent être manipulés depuis les sous-classes via le mot-clé `this` (comme s'ils y avaient été définis).
|
|
:book: Lorsque des attributs ou méthodes hérités sont visibles, ils peuvent être manipulés depuis les sous-classes via le mot-clé `this` (comme s'ils y avaient été définis).
|
|
|
|
|
|
|
|
<!-- TOC --><a name="constructeurs-de-la-sous-classe"></a>
|
|
# Constructeurs de la sous-classe
|
|
# Constructeurs de la sous-classe
|
|
|
|
|
|
:book: Le constructeur d'une classe dérivée doit prendre en charge l'intégralité de la construction de l'objet, c'est à dire initialiser tous les attributs (hérités et ajoutés)
|
|
:book: Le constructeur d'une classe dérivée doit prendre en charge l'intégralité de la construction de l'objet, c'est à dire initialiser tous les attributs (hérités et ajoutés)
|
... | @@ -110,6 +118,7 @@ Spécifiquement, la classe `Worker`: |
... | @@ -110,6 +118,7 @@ Spécifiquement, la classe `Worker`: |
|
|
|
|
|
:book: le constructeur de la classe dérivée peut s'appuyer sur le constructeur de la super-classe, en l'appelant et en lui passant des paramètres via `super(...)`. Si cet appel a lieu, ce doit être la première instruction du constructeur de la sous-classe.
|
|
:book: le constructeur de la classe dérivée peut s'appuyer sur le constructeur de la super-classe, en l'appelant et en lui passant des paramètres via `super(...)`. Si cet appel a lieu, ce doit être la première instruction du constructeur de la sous-classe.
|
|
|
|
|
|
|
|
<!-- TOC --><a name="redéfinition-de-méthode"></a>
|
|
# Redéfinition de méthode
|
|
# Redéfinition de méthode
|
|
|
|
|
|
:book: La redéfinition d'une méthode dans la classe dérivée permet soit de remplacer intégralement celle de la classe de base, soit de la compléter en s’appuyant sur celle-ci.
|
|
:book: La redéfinition d'une méthode dans la classe dérivée permet soit de remplacer intégralement celle de la classe de base, soit de la compléter en s’appuyant sur celle-ci.
|
... | @@ -124,6 +133,7 @@ Spécifiquement, la classe `Worker`: |
... | @@ -124,6 +133,7 @@ Spécifiquement, la classe `Worker`: |
|
|
|
|
|
:book: Dans la redéfinition d'une méthode, on peut s'appuyer sur la super-méthode en l'invocant via le mot-clé `super` (au lieu de `this`).
|
|
:book: Dans la redéfinition d'une méthode, on peut s'appuyer sur la super-méthode en l'invocant via le mot-clé `super` (au lieu de `this`).
|
|
|
|
|
|
|
|
<!-- TOC --><a name="liaison-tardive-lookup"></a>
|
|
# Liaison tardive (*lookup*)
|
|
# Liaison tardive (*lookup*)
|
|
|
|
|
|
:book: En Java, l’invocation de méthode sur un objet suit un principe appelé **liaison tardive** (ou _lookup_). Le code exécuté lors de l'appel à une méthode sur un objet est celui de la première méthode visible conforme à la signature en **cherchant à partir de la classe et en remontant l’arbre d’héritage**.
|
|
:book: En Java, l’invocation de méthode sur un objet suit un principe appelé **liaison tardive** (ou _lookup_). Le code exécuté lors de l'appel à une méthode sur un objet est celui de la première méthode visible conforme à la signature en **cherchant à partir de la classe et en remontant l’arbre d’héritage**.
|
... | @@ -145,6 +155,7 @@ Lors de l'appel à `person.exportVCard()`, le code exécuté est celui de la mé |
... | @@ -145,6 +155,7 @@ Lors de l'appel à `person.exportVCard()`, le code exécuté est celui de la mé |
|
|
|
|
|
Lors de l'appel à `worker.exportVCard()`, le code exécuté est celui de la méthode `exportVCard` de la classe `Worker` puisqu'il s'agit d'une méthode redéfinie dans la classe correspondant au type de l'objet et qu'elle y est visible car publique.
|
|
Lors de l'appel à `worker.exportVCard()`, le code exécuté est celui de la méthode `exportVCard` de la classe `Worker` puisqu'il s'agit d'une méthode redéfinie dans la classe correspondant au type de l'objet et qu'elle y est visible car publique.
|
|
|
|
|
|
|
|
<!-- TOC --><a name="retour-sur-le-polymorphisme"></a>
|
|
# Retour sur le polymorphisme
|
|
# Retour sur le polymorphisme
|
|
|
|
|
|
:rewind: Le polymorphisme est lié à la **faculté pour un objet de pouvoir être vu à travers tous les types avec lesquels il est compatible**.
|
|
:rewind: Le polymorphisme est lié à la **faculté pour un objet de pouvoir être vu à travers tous les types avec lesquels il est compatible**.
|
... | @@ -190,6 +201,7 @@ Person person = worker; |
... | @@ -190,6 +201,7 @@ Person person = worker; |
|
|
|
|
|
:bulb: Cependant, lors d'un appel à `person.exportVCard`, le code exécuté sera bien celui défini par `Worker` car il s'agit de la classe correspondant à celui de l'objet et que la méthode y est redéfinie.
|
|
:bulb: Cependant, lors d'un appel à `person.exportVCard`, le code exécuté sera bien celui défini par `Worker` car il s'agit de la classe correspondant à celui de l'objet et que la méthode y est redéfinie.
|
|
|
|
|
|
|
|
<!-- TOC --><a name="classe-object"></a>
|
|
# Classe `Object`
|
|
# Classe `Object`
|
|
|
|
|
|
:book: en Java, la classe `Object` est la racine de tous les arbres d'héritage (autrement dit toutes les classes héritent directement ou indirectement de `Object`)
|
|
:book: en Java, la classe `Object` est la racine de tous les arbres d'héritage (autrement dit toutes les classes héritent directement ou indirectement de `Object`)
|
... | @@ -215,6 +227,7 @@ protected void finalize() { // nettoyage avant suppression de l'objet } |
... | @@ -215,6 +227,7 @@ protected void finalize() { // nettoyage avant suppression de l'objet } |
|
:pencil: Si l'on invoque les méthodes `equals`, `toString` ou `hashCode` sur les objets référencés par les variables `person` ou `worker` évoquées précédemment, le mécanisme de lookup conduira dans tous les cas à exécuter le code défini dans la classe `Object` puisque ni `Person` ni `Worker` ne redéfinissent ces méthodes.
|
|
:pencil: Si l'on invoque les méthodes `equals`, `toString` ou `hashCode` sur les objets référencés par les variables `person` ou `worker` évoquées précédemment, le mécanisme de lookup conduira dans tous les cas à exécuter le code défini dans la classe `Object` puisque ni `Person` ni `Worker` ne redéfinissent ces méthodes.
|
|
|
|
|
|
|
|
|
|
|
|
<!-- TOC --><a name="méthode-equals"></a>
|
|
## Méthode `equals`
|
|
## Méthode `equals`
|
|
|
|
|
|
:book: La méthode `equals` est utilisée par un certain nombre d'algorithmes génériques de la librairie standard afin de savoir si 2 objets sont logiquement identiques.
|
|
:book: La méthode `equals` est utilisée par un certain nombre d'algorithmes génériques de la librairie standard afin de savoir si 2 objets sont logiquement identiques.
|
... | @@ -283,6 +296,7 @@ public class Identity { |
... | @@ -283,6 +296,7 @@ public class Identity { |
|
|
|
|
|
:pencil: Dans l'exemple, `Indentity other = (Indentity) o` force le type de la référence `o` pour pouvoir l'affecter à une variable de type `Identity` pour pouvoir manipuler pleinement l'objet.
|
|
:pencil: Dans l'exemple, `Indentity other = (Indentity) o` force le type de la référence `o` pour pouvoir l'affecter à une variable de type `Identity` pour pouvoir manipuler pleinement l'objet.
|
|
|
|
|
|
|
|
<!-- TOC --><a name="méthode-hashcode"></a>
|
|
## Méthode `hashCode`
|
|
## Méthode `hashCode`
|
|
|
|
|
|
:book: La méthode `hashCode` doit retourner une **valeur de hachage** qui est en quelque sorte un résumé de l'état de l'objet (valeur entière sur 32 bits) destinée à classer/retrouver un objet rapidement et très utilisée notamment dans la bibliothèque de gestion de collections d'objets.
|
|
:book: La méthode `hashCode` doit retourner une **valeur de hachage** qui est en quelque sorte un résumé de l'état de l'objet (valeur entière sur 32 bits) destinée à classer/retrouver un objet rapidement et très utilisée notamment dans la bibliothèque de gestion de collections d'objets.
|
... | @@ -291,6 +305,7 @@ public class Identity { |
... | @@ -291,6 +305,7 @@ public class Identity { |
|
|
|
|
|
:rocket: Résumer un objet à 32 bits conduit inévitablement à des collisions. Par exemple, pour une classe `Position` définissant 2 attributs `x` et `y` de type `int` (donc sur 32 bits), il existera `2^32*2^32` états d'objets distincts logiquement, correspondant à l'ensemble des couples `x/y` différents. Comme il existe `2^32` valeurs de hashCode, il y aura un grand nombre de collisions. Toute la subtilité consiste à choisir une fonction de hachage répartissant de manière homogène les états d'objets sur chaque valeur de hashcode. Dans le cas de la classe `Position`, l'idéal serait d'avoir `2^32` états d'objets par valeur de hashcode. Sans chercher la perfection, ici, utiliser `x+y` comme fonction de hachage ne serait déjà pas si mal.
|
|
:rocket: Résumer un objet à 32 bits conduit inévitablement à des collisions. Par exemple, pour une classe `Position` définissant 2 attributs `x` et `y` de type `int` (donc sur 32 bits), il existera `2^32*2^32` états d'objets distincts logiquement, correspondant à l'ensemble des couples `x/y` différents. Comme il existe `2^32` valeurs de hashCode, il y aura un grand nombre de collisions. Toute la subtilité consiste à choisir une fonction de hachage répartissant de manière homogène les états d'objets sur chaque valeur de hashcode. Dans le cas de la classe `Position`, l'idéal serait d'avoir `2^32` états d'objets par valeur de hashcode. Sans chercher la perfection, ici, utiliser `x+y` comme fonction de hachage ne serait déjà pas si mal.
|
|
|
|
|
|
|
|
<!-- TOC --><a name="méthode-tostring"></a>
|
|
## Méthode `toString`
|
|
## Méthode `toString`
|
|
|
|
|
|
:book: La méthode `toString` doit retourner une description textuelle de l’objet sous la forme d'une chaine de caractères.
|
|
:book: La méthode `toString` doit retourner une description textuelle de l’objet sous la forme d'une chaine de caractères.
|
... | @@ -299,6 +314,7 @@ public class Identity { |
... | @@ -299,6 +314,7 @@ public class Identity { |
|
|
|
|
|
:rocket: La méthode `toString` est appelée systématiquement et implicitement lorsqu’une transformation d’objet en chaîne de caractères est nécessaire, comme par exemple en cas de concaténation d’un objet à une chaîne de caractères. Ainsi `System.out.println(o)` suffit pour afficher dans la console la représentation texte de l'objet référencé par `o`.
|
|
:rocket: La méthode `toString` est appelée systématiquement et implicitement lorsqu’une transformation d’objet en chaîne de caractères est nécessaire, comme par exemple en cas de concaténation d’un objet à une chaîne de caractères. Ainsi `System.out.println(o)` suffit pour afficher dans la console la représentation texte de l'objet référencé par `o`.
|
|
|
|
|
|
|
|
<!-- TOC --><a name="retour-sur-les-énumérations"></a>
|
|
# Retour sur les énumérations
|
|
# Retour sur les énumérations
|
|
|
|
|
|
Comme illustré ci-dessous, toute énumération **étend implicitement la classe `Enum`** dont elle hérite d'attributs et des _getters_ associés :
|
|
Comme illustré ci-dessous, toute énumération **étend implicitement la classe `Enum`** dont elle hérite d'attributs et des _getters_ associés :
|
... | | ... | |