Patrons de conception/Type fantôme
En général, un type de données est créé afin de pouvoir utiliser ses valeurs possibles.
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 |
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.
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.