Accès rapide :
La vidéo
Implémentation d'une classe générique
Utilisation de notre classe générique
Restriction du typage sur une classe générique
Cette vidéo vous montre comment coder une classe générique en Java ainsi que comment l'utiliser. La restriction des types utilisables par votre classe générique, vous est aussi présentée.
Nous allons maintenant apprendre à coder une classe générique. Pour indiquer qu'un type est générique, il faut ajouter la liste des types génériques
supportés entre caractères <
et >
à la suite du nom de la classe et avant l'accolade ouvrante.
1 2 3 4 5 |
public class GenericBox<ELEMENT> { // TODO: implémentation de la classe générique } |
ELEMENT
.
Java préconise des conventions de codage : il y est dit qu'un nom de type générique doit être une seule lettre en majuscule pour le différentier d'un nom
de type classique. Personnellement, je préfère mettre un nom complet indiquant bien ce qu'il représente. Dans le cas considéré, ce type de généricité se nomme
ELEMENT
.
Il est possible de définir une classe générique avec plusieurs types de généricité.
Par exemple, nous avons parlé dans le chapitre précédent du type java.util.Map
qui manipule des clé et des valeurs
Pour définir une telle classe, séparez vos types de généricité avec des virgules. Voici un exemple de syntaxe.
1 2 3 4 5 |
public class MyMap<KEY, VALUE> { // TODO: implémentation de la classe générique } |
Reprenons l'exemple de notre classe GenericBox
à un type de généricité.
Il faut maintenant définir les attributs et les méthodes qui vont constituer cette classe. Ces membres vont certainement devoir utiliser le type de
généricité : utilisez simplement le nom ELEMENT
pour y faire référence. Voici le contenu de notre classe générique.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class GenericBox<ELEMENT> { private ELEMENT element; public GenericBox( ELEMENT element ) { this.setElement( element ); } public ELEMENT getElement() { return element; } public void setElement( ELEMENT element ) { if ( element == null ) throw new NullPointerException( "null is not permit" ); this.element = element; } // Other methods } |
Nous allons maintenant utiliser notre type générique. Nous allons créer une instance de la classe GenericBox
en la spécialisant sur le type
String
. Le constructeur et les méthodes getElement
et setElement
manipuleront donc des chaînes de caractères.
1 2 3 4 5 6 7 8 9 10 11 12 |
public class Start { public static void main(String[] args) { GenericBox<String> box = new GenericBox<>( "toto" ); System.out.println( box.getElement() ); box.setElement( "tata" ); System.out.println( box.getElement() ); } } |
Il est possible de limiter les types utilisables pour une classe générique. Par exemple, si l'on souhaite que notre classe GenericBox
soit limitée à des types dérivant d'une classe Person
(imaginez plusieurs classes qui dérivent de cette classe Person
),
utilisez la syntaxe suivante.
1 2 3 4 5 |
public class GenericBox<ELEMENT extends Person> { // TODO: implémentation de la classe générique } |
Voici un exemple plus complet qui permet d'envelopper n'importe quel composant Swing dans une fenêtre. Les types utilisables sont donc limités à n'importe
quel composant graphique (dérivant de java.awt.Component
).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
import java.awt.BorderLayout; import java.awt.Component; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTree; @SuppressWarnings( {"serial", "unused"} ) public class GenericContainer<COMPONENT extends Component> extends JFrame { private COMPONENT myComponent; public GenericContainer( COMPONENT component ) { super( "Generic Container" ); this.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE ); JPanel contentPane = (JPanel) getContentPane(); contentPane.add( component, BorderLayout.CENTER ); this.pack(); this.setLocationRelativeTo( null ); this.setVisible( true ); } public COMPONENT getMyComponent() { return myComponent; } // Le point d'entrée de notre programme public static void main(String[] args) { // Deux exemples d'utilisation de notre classe générique // sur un bouton et un composant de type JTree GenericContainer<JButton> frame = new GenericContainer<>( new JButton("Click me!") ); JButton btn = frame.getMyComponent(); GenericContainer<JTree> frame2 = new GenericContainer<>( new JTree() ); JTree tree = frame2.getMyComponent(); // Par contre, cette ligne de code ne compile pas, car une chaîne // de caractères n'est pas un composant graphique. //GenericContainer<String> frame = new GenericContainer<>( "toto" ); } } |
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :