Patrons de conception/Type fantôme
Apparence
Patron de conception | |
---|---|
Catégorie : Autre | |
Nom français : | Type fantôme |
Nom anglais : | Phantom type |
Utiliser un type pour détecter des erreurs plutôt que pour ses valeurs possibles |
En général, un type de données est créé afin de pouvoir utiliser ses valeurs possibles.
Un type fantôme n'est utilisé que pour ajouter une contrainte qui puisse être vérifiée à la compilation. Cette fonctionnalité est utilisable avec la programmation fonctionnelle et également la programmation orientée objet en utilisant les templates ou types génériques.
Exemple en Java
[modifier | modifier le wikicode]Cet exemple utilise une classe dont les instances peuvent être en lecture seule ou écriture seule.
public class PName<V>
{
// Types fantômes utilisés pour marquer les méthodes
// dont les appels seront vérifiés à la compilation.
public static interface ReadOnly { }
public static interface WriteOnly { }
public static interface ReadWrite extends ReadOnly, WriteOnly { }
// Des interfaces sont utilisées au lieu de classes afin que
// ReadWrite hérite des deux types précédents.
private String name;
private PName(String s) { this.name = s; }
public static PName<ReadWrite> pname(String s) { return new PName<ReadWrite>(s); }
public static PName<ReadOnly> readOnly(String s) { return new PName<ReadOnly>(s); }
public static PName<WriteOnly> readWrite(String s) { return new PName<WriteOnly>(s); }
// Opérations de conversion
@SuppressWarnings("unchecked")
public static PName<ReadOnly> readable(PName<? extends ReadOnly> pname)
{ return (PName<ReadOnly>) pname; }
@SuppressWarnings("unchecked")
public static PName<WriteOnly> writeable(PName<? extends WriteOnly> pname)
{ return (PName<WriteOnly>) pname; }
// Opérations de lecture et d'écriture
public static int get(PName<? extends ReadOnly> pname)
{ return pname.name; }
public static void set(PName<? extends WriteOnly> pname, String v)
{ pname.name = v; }
public static void main(String[] args) // Test
{
// Nom en lecture et écriture
PName<ReadWrite> rw = pname("Test");
System.out.println(get(rw)); // Lecture OK
set(rw,"Exemple"); // Écriture OK
System.out.println(get(rw)); // Lecture OK
// Version en lecture seule
PName<ReadOnly> ro = readable(rw);
System.out.println(get(ro)); // Lecture OK
//set(ro,"Autre"); // Écriture --> erreur à la compilation
// Version en écriture seule
PName<WriteOnly> wo = writeable(rw);
set(wo,"Modification"); // Écriture OK
//get(wo); // Lecture --> erreur à la compilation
}
}
Les types ReadOnly
, WriteOnly
et ReadWrite
sont des types fantômes (aucune instance existante) utilisés uniquement pour marquer le type PName
et que le compilateur puisse effectuer les vérifications.