42 votes

Java Génériques application compatible caractères génériques

J'ai ces classes.

class RedSocket {}
class GreenSocket {}
class RedWire {}
class GreenWire {}

J'ai une classe qui utilise 2 types génériques

public class Connection<W, S> {}

où W est le type de Fil & S est de type Socket.

Je suis en train de faire respecter les temps de compilation, vérifiez que le socket et les fils de la même couleur.

J'ai essayé de faire ceci:

public class Connection<W extends Wire & Color, S extends Socket & Color> {}

interface Color {}

interface Red extends Color {}
interface Green extends Color {}

interface Socket {}
interface Wire {}

class RedSocket implements Socket, Red {}
class GreenSocket implements Socket, Green {}
class RedWire implements Wire,  Red {}
class GreenWire implements Wire, Green {}

Mais ce n'est pas vraiment de s'assurer que l' Color utilisé est le même pour les deux types génériques et encore me permet de faire ceci:

public class Connection<W extends Wire & Color, S extends Socket & Color> {
    public static void main(String[] args) {
        new Connection<RedWire, GreenSocket>();
        new Connection<GreenWire, RedSocket>();
    }
}

(Le pourquoi de ce phénomène a été expliqué avec brio par Radiodef ici)

Comment puis-je m'assurer de la compilation, vérifiez que le socket et les fils de la même couleur?

55voto

Tagir Valeev Points 14218

Semble qu'il est préférable de paramétrer Socket et Wire avec de la couleur:

interface Socket<C extends Color> {}
interface Wire<C extends Color> {}

class RedSocket implements Socket<Red> {}
class GreenSocket implements Socket<Green> {}
class RedWire implements Wire<Red> {}
class GreenWire implements Wire<Green> {}

De cette façon, vous pouvez introduire un plus générique paramètre à l' Connection:

public class Connection<C extends Color, M extends Wire<C>, Q extends Socket<C>> {...}

Et de l'utiliser comme ceci:

new Connection<Red, RedWire, RedSocket>(); // ok
new Connection<Green, GreenWire, GreenSocket>(); // ok
new Connection<Green, GreenWire, RedSocket>(); // error

35voto

Marco13 Points 14743

Comme une variation mineure de Tagir Valeev réponse: Vous pouvez éventuellement se débarrasser de la troisième paramètre générique de l' Connection classe, en faisant de son constructeur private (ou peut-être paquet visible), et de proposer une méthode de fabrique pour la création d' Connection instances qui assure que l' Color type est le même pour l' Wire- et Socket types de:

class Connection<
    W extends Wire<? extends Color>, 
    S extends Socket<? extends Color>> 
{
    static <C extends Color, 
        W extends Wire<C>, 
        S extends Socket<C>> Connection<W, S> create()
    {
        return new Connection<W, S>();        
    }

    // Private constructor
    private Connection() {}
}

interface Color {}

interface Red extends Color {}
interface Green extends Color {}

interface Socket<C extends Color> {}
interface Wire<C extends Color> {}

class RedSocket implements Socket<Red> {}
class GreenSocket implements Socket<Green> {}
class RedWire implements Wire<Red> {}
class GreenWire implements Wire<Green> {}

public class CompatibleGenericsTest
{
    public static void main(String[] args)
    {
        Connection<RedWire, RedSocket> c0 = Connection.create(); // ok
        Connection<GreenWire, GreenSocket> c1 = Connection.create(); // ok
        Connection<GreenWire, RedSocket> c2 = Connection.create(); // error
    }
}

3voto

Danikov Points 238

Une tentative de mélanger-dans un arbitraire correctement comme "Couleur" est un exemple typique de déclenchement pour l'ensemble de l'héritage vs composition aka. est-a-a-un débat. Le général de sagesse pour un langage tel que Java est que l'on doit privilégier la composition au cours de l'héritage dans la plupart des cas généraux afin d'éviter des choses comme délicate des caractères génériques. D'autres langues peuvent offrir plus dans le sens de la programmation orientée aspects

Alors que d'autres réponses peuvent vous aider à atteindre corriger les génériques, je vous suggère de lire sur la page de wikipedia sur le sujet et savoir si vous avez vraiment besoin pour appliquer la couleur correspondant au moment de la compilation ou si l'exécution du constructeur de vérifier pour faire le travail.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X