2010-05-21 11 views
4

Le code suivant ne fonctionne évidemment pas parce que List<E> est abstraite:Comment initialiser la liste <E> dans le constructeur de classe vide?

public class MyList { 
    private List<E> list; 

    public MyList() { 
     this.list = new List<E>(); 
    } 
} 

Comment puis-je initialiser MyList classe avec un constructeur vide si je dois la variable list être un LinkedList ou ArrayList en fonction de mes besoins?

+0

La liste n'est pas marquée comme définitive. Est-ce qu'il doit être initialisé dans le ctor? –

+0

Oui, il doit être initialisé dans le constructeur. –

+0

Est-ce qu'une classe d'usine utilitaire est acceptable? A partir des commentaires, j'ai l'impression que vous voulez que le type d'implémentation soit configurable, et cela suggère une Usine, utilisée par MyList. – extraneon

Répondre

2

Il existe de meilleures alternatives pour ce que vous essayez d'atteindre:

  • Créer une classe de base (? Abstraite) et la remplacer à deux reprises, une fois pour ArrayList et un pour LinkedList
  • Injecter la liste appropriée à votre classe (injection de dépendances)
+0

J'avais une question à ce sujet il y a quelques heures et quelqu'un m'a recommandé cette solution à la place, regardez ici: http://stackoverflow.com/questions/2881684/help-with-abstract-class-in-java-with-private- variable-of-type-liste –

1
boolean shouldThisBeAnArrayList=true; // Set to false to use LinkedList 
if(shouldThisBeAnArrayList) { 
    this.list = new ArrayList<E>(); 

} 
else { 
    this.list=new LinkedList<E>(); 
} 
+0

Comme je l'ai dit dans un autre commentaire, cela irait à l'encontre du but d'un «constructeur vide», n'est-ce pas? Je veux dire, je devrais passer la valeur de 'shouldThisBeAnArrayList' d'une façon ou d'une autre ... –

7

Je ne suis pas sûr que ce soit ce que vous demandez ...

public class MyList { 
    private List<E> list; 

    public MyList() { 
     if (myNeeds) 
      this.list = new LinkedList<E>(); 
     else 
      this.list = new ArrayList<E>(); 
    } 
} 
+0

Sorte de ... Je pensais à une solution comme ça mais j'ai demandé ici parce que je pensais que peut-être il y avait une meilleure façon, d'une façon ou d'une autre. N'est-ce pas que myNeeds doit être passé en argument dans le constructeur? Cela irait à l'encontre du but du "constructeur vide". –

+0

Eh bien, comment l'objet va-t-il savoir quel type utiliser? Il doit soit être transmis au constructeur, soit être disponible via l'environnement (par exemple, une classe singleton). – Thomas

+0

C'est pourquoi j'ai posté la question sur SO ... –

0

Je pense que vous pouvez faire ce qui suit:

public class MyList<T> { 
    private List<T> list; 

    public MyList() { 
     this.list = new ArrayList<T>(); 
    } 
} 
+0

Comment cela fonctionnerait-il quand j'ai besoin d'un 'LinkedList' au lieu d'un' ArrayList'? –

+0

@Nazgulled où voulez-vous configurer le type de liste? Par objet ou peut-être dans certains fichiers de propriétés de démarrage? – extraneon

+0

J'ai besoin qu'il soit par objet ... –

1

Vous devez déterminer quels "vos besoins" sont dans le cas par défaut - LinkedList ou ArrayList. Si vous ne pouvez pas, disons, si le besoin change en fonction de quelque chose qui arrive pendant la durée de vie de l'objet, la liste doit également changer.

+0

Il ne peut pas y avoir de cas par défaut ... –

+1

Ensuite, laissez-le vide et créez-le à la demande, ou faites-en sans le constructeur par défaut. –

1

La liste est une interface et, en tant que telle, ne peut pas être construite. Seules les implémentations de ladite interface peuvent être construites (par exemple ArrayList). Aussi, vous devez connaître le type (E) à la construction.

Cela devrait fonctionner:

import java.util.ArrayList; 
import java.util.LinkedList; 
import java.util.List; 

public class MyList<E> { 
    private List<E> list; 

    public MyList(boolean linked) { 
     if (linked) { 
      list = new LinkedList<E>(); 
     } else { 
      list = new ArrayList<E>(); 
     } 
    } 
} 
+0

Cette fois quelqu'un m'a suggéré cela mais comme je l'ai dit, cela ne va-t-il pas à l'encontre du but de "constructeur vide"? Mais peut-être qu'il n'y a pas d'autre moyen ...: | –

+0

Vous pouvez construire une LinkedList par défaut et avoir une méthode setListType qui construirait une nouvelle ArrayList et copierait les données de LinkedList dans celle-ci. –

2

Pourquoi ne pas utiliser un protégé (et peut-être abstract méthode) comme:

public abstract class MyList<T> { 

    protected final List<T> list; 

    public MyList() { 
     list = createList(); 
    } 

    public MyList(boolean preferLinked) { 
     list = preferLinked? new LinkedList<T>() : new ArrayList<T>(); 
    } 

    // Allows client code which subclasses from MyList to override the 
    // default behaviour 

    protected List<T> createList() { 
     return new ArrayList<T>(); 
    } 
} 
0

Si je comprends bien, vous ne pouvez pas utiliser juste un constructeur vide, parce que vous avez un nœud de décision dans votre modèle, quand vous avez besoin de choisir entre le type de la liste, vous devrez donc indiquer au programme quel type de liste sera. Cela semble être la meilleure solution à mon avis:

public class MyList { 
    private List<E> list; 

    public MyList() { 
     this.list = new LinkedList<E>(); 
    } 

    //an overload for another type, 
    public MyList(bool INeedArray) { 
     if (INeedArray) 
     this.list = new ArrayList<E>(); 
    } 
} 
0
public class MyList<T> { 
    private List<T> list = new ArrayList<T>(); 
} 

Voici ce que j'utiliser dans les classes .. J'ai depuis longtemps initialisés ce que je pouvais lors de la définition de la variable self privée elle.