2011-10-20 3 views
0

Je crée plusieurs fonctions dans lesquelles je veux retourner l'interface au lieu de l'implémentation, I.E. Liste au lieu de ArrayList. Ma méthode signature et une brève mise en œuvre suit:Java 6 Collections.checkedList utilisation appropriée

public List<MyAwesomeComposedObject> convert(Collection<MyAwesomeObject> awesomeObjects>) 
{ 
    List<MyAwesomeComposedObject> composedObjects = new ArrayList<MyAwesomeComposedObject>(); 
    for(MyAwesomeObject awesomeObject : awesomeObjects) 
    { 
     MyAwesomeComposedObject composedObject = new MyAwesomeComposedObject(awesomeObject); 
     composedObjects.add(composedObject); 
    } 

    List<MyAwesomeComposedObject> composedObjectList = Collections.checkedList<composedObjects, MyAwesomeComposedObject.class); 
    return composedObjectList; 
} 

Ma question est, est-ce un anti-modèle de quelque sorte? Je veux garantir que l'invocateur de cette méthode obtient l'interface au lieu d'une implémentation. Je ne crois pas non plus qu'il s'agisse d'un cas de sur-ingénierie. Si ce n'est pas la bonne façon de retourner une interface, dans ce scénario, je suis ouvert à l'implémentation correcte.

Attaché est un petit programme qui donne lieu à une exception:

public static void main(String[] args) 
{ 
    Vector v = (Vector) c(); 
} 

static List<Object> c() 
{ 
    List<Object> l = new ArrayList<Object>(); 
    l.add(new Object()); 
    List<Object> o = Collections.checkedList(l, Object.class); 
    return o; 
} 

Le javadoc est ici: checked list

+2

Je ne vois pas quel est le problème; la signature de la méthode garantit que l'appelant obtient une «liste » par définition. –

+0

J'ai mis à jour ma question, Vector implémente l'interface List, ce code ci-dessus échoue. – Woot4Moo

+2

Il échoue car un 'ArrayList' n'est pas un' Vector'. C'est pourquoi les codeurs ne devraient pas passer d'une interface à un type concret à moins qu'ils ne soient absolument sûrs que l'instance est vraiment une instance du type concret. Il n'y a aucun moyen d'empêcher les gens de faire des choses mal avisées comme celles-ci, sauf l'éducation. –

Répondre

1

Pour votre question révisée: Il n'y a aucun moyen d'empêcher l'appelant de tenter de jeter à tout ce qu'ils veulent. Si c'est un casting inapproprié, ils auront l'exception. C'est la raison même pour laquelle la conversion d'une interface en une classe concrète est fortement déconseillée.

Si vous êtes vraiment inquiet à ce sujet, pensez à renvoyer un ArrayList au lieu d'un List. Cela devrait décourager le lancer puisqu'ils sont en béton. S'il vous plaît noter que je ne cautionne pas cela, c'est juste une option.

Je veux garantir que l'invocateur de cette méthode devient l'interface au lieu d'une mise en œuvre

Ce n'est pas valide. Vous renvoyez un List où le type déclaré des éléments est une interface, mais chaque élément doit être une instanciation. Tout ce que fait une collection vérifiée empêche l'ajout d'éléments du type incorrect. Rien n'empêche l'utilisateur de revenir au type d'implémentation.

Si vous essayez de faire en sorte que l'utilisateur obtient List au lieu de ArrayList (je suppose ici parce que je ne vois pas d'interface pour vous classe impressionnante), ce nouveau est défectueux parce que l'utilisateur pourrait encore jeter le List à un ArrayList bien que ce serait une mauvaise idée car il risque un ClassCastException.

+0

Corriger chaque élément doit être une instanciation, je fais référence à l'implémentation de 'collection'. Je veux être capable d'éviter une exception de cast de classe si elle est introduite dans un vecteur ou toute autre implémentation de List. – Woot4Moo

+0

@ Woot4Moo voir mise à jour pour répondre et commenter à la question –

+0

merci pour la mise à jour. Je veux également éviter d'avoir ArrayList dans la signature. Basé sur la réponse de Peter il semblerait possible que mon approche puisse fonctionner, je veux savoir si je le regarde dans la lumière complètement fausse. Je commence à croire que je peux très bien le faire. – Woot4Moo

2

La liste retournée est un Collections.CheckedList pas un vecteur. Vous ne pouvez pas faire référence à un type que l'objet n'est pas.

Cependant ce que vous pouvez faire est

public static void main(String[] args) { 
    Vector<Object> v = new Vector<Object>(c()); 
} 

composedObjects est déjà une liste, vous pouvez le retourner.

public List<MyAwesomeComposedObject> convert(Collection<MyAwesomeObject> awesomeObjects>) { 
    List<MyAwesomeComposedObject> composedObjects = new ArrayList<MyAwesomeComposedObject>(); 
    for(MyAwesomeObject awesomeObject : awesomeObjects)  
     composedObjects.add(new MyAwesomeComposedObject(awesomeObject)); 
    return composedObjects; 
} 
+0

J'ai mis à jour ma question pour montrer l'exception que je veux éviter, ce qui à son tour peut signifier que j'ai mal posé la question. – Woot4Moo

+0

Merci pour la mise à jour Peter. Mon approche est-elle valide alors pour s'appuyer sur la méthode Collections.checkedList? – Woot4Moo

+0

checkedList est utile pour vérifier à l'exécution que les types d'entrées ajoutées sont corrects. Vous ne semblez pas avoir ce problème dans votre exemple. –