2009-05-25 10 views

Répondre

10

Il semble vaincre le but de generics, mais ici il va:

Stack<Object>s = new Stack<Object>(); 
s.add("hello"); 
s.add(1);   // int is autoboxed to Integer 

La capture sera que lors de la récupération des Object s de la Stack, il va prendre un certain effort pour savoir quel type de chaque élément est - il faudra l'aide instanceof et typecasts:

while (!s.isEmpty()) { 
    Object e = s.pop(); 

    if (e instanceof String) 
    System.out.println("String: " + (String)e); 
    else if (e instanceof Integer) 
    System.out.println("Integer: " + (Integer)e); 
    else 
    System.out.println("Other type: " + e); 
} 

et maintenant, nous avons quelque chose qui ressemble au code fragile de la pré-Java 5 jours avant les médicaments génériques a été ajouté à la langue.

+1

Le danger est lorsque vous récupérez les éléments plus tard, vous devez écrire des contrôles pour les types d'objets. – Joset

+0

Absolument - Je viens juste d'ajouter cette partie en tant que modification. – coobird

6

Généralement, vous devrez résoudre ceci en utilisant l'héritage. Peut-être en utilisant une interface marqueur:

interface MyMarker 
{ 
} 

class Foo implements MyMarker 
{ 
} 

class Bar implements MyMarker 
{ 
} 

Interfaces sont pratiques dans des cas comme celui-ci, parce que vous pouvez mettre en œuvre un nombre illimité d'interfaces dans une seule classe, et vous pouvez ajouter des interfaces supplémentaires partout dans le hierchy de classe.

Vous pouvez ensuite mettre Foo et Bar dans la même pile:

Stack<MyMarker> s = new Stack<MyMarker>(); 
s.add(new Foo()); 
s.add(new Bar()); 

C'est le chemin à parcourir si elle est possible. Sinon, vous devrez le faire comme coobird suggère.

+2

C'est certainement un meilleur moyen - chaque fois qu'il y a une échelle if-elseif de "instanceof", la solution est généralement l'héritage. – coobird

0

L'argument générique de la pile doit être un super-type commun de tous les types d'exécution d'élément. Pour les collections complètement hétérogènes, Object est le super-type commun de tous les types de référence. Alors:

Queue<Object> stack = Collections.asLifoQueue(new ArrayDeque<Object>()); 
stack.add("red"); 
stack.add(Color.GREEN); 
stack.add(stack); 

Il est évident que lorsque vous venez à la pop ces éléments de la pile, vous devez faire vérifier instanceof pour acheminer le code approprié (et probablement jeté).

Probablement préférable d'introduire une couche d'indirection. Au lieu de placer directement les objets dans la file d'attente, enveloppez-les dans un objet significatif. Les contrôles instanceof peuvent tous être remplacés par des appels à des méthodes (virtuelles) qui effectuent les opérations dont vous avez besoin. C'est ainsi que le polymorphisme est censé être.