6
votes

Devrais-je prolonger une arrayliste (IS-A) ou devrais-je y inclure en tant que membre (AI-A)?

Je fais un programme simple qui maintient une liste de chiffres et je souhaite que cette liste ait également un nom. Quelle est la meilleure approche: demandez à ma classe de liste d'étendre l'arraylist ou d'inclure un membre de l'arraylist? Dans les deux cas, il y aurait bien sûr un membre de la chaîne "Nom".

La première approche signifie que je n'ai que je dois implémenter un getter & Setter pour le nom, mais je pense que cela attacherait ma classe trop étroitement à une mise en œuvre particulière? Par exemple, si je voulais utiliser plus tard un vecteur, je devrais changer de code partout.

La deuxième approche faciliterait la modification de la mise en œuvre, mais devient bien sûr assez gênante pour le moment, car je dois mettre en œuvre un groupe d'emballages.

J'ai lu les posts sur l'héritage par rapport à la composition et, étant donné que ma liste est un type de arrayliste, je me penche vers la première approche. Cependant, y a-t-il des différences pour la discussion parce que je prolonge que la classe de collection vs étendue une classe générale? Ou suis-je sur-pensant cela?


0 commentaires

6 Réponses :


2
votes

Ni est meilleur, c'est un compromis comme vous l'avez mentionné.

Si vous accrochez (AI-A), vous devez envelopper toutes les fonctionnalités du membre que vous allez utiliser (c'est-à-dire des fonctions de mise en œuvre qui les appellent)

Si vous y hériter, de nombreuses fonctions sont ajoutées à votre nouvelle classe, ce qui pourrait être non synchronisé, et vous devez également mettre en œuvre des fonctions abstraites.

Si vous étiez dans un environnement C ++, l'héritage privé serait une option, mais ici à la fois des avantages et des contre


2 commentaires

Une solution nécessitant plus de travail à mettre en œuvre ne signifie pas que cela ne peut pas encore être objectivement meilleur que l'autre.


Vous avez raison mais cette solution n'a pas besoin d'effort humain, peut être automatisé d'outils. Par conséquent, pas considéré dans Trafe Off



1
votes

composition - a-a. Je préfère cela pour les collections de toutes les rayures.


1 commentaires

Pourriez-vous donner des raisons de préférence de composition?



3
votes

À long terme, il est généralement préférable d'inclure en tant que membre que de s'étendre. De cette façon, il est plus explicite ce que vous voulez permettre, ce qui facilite la test et maintenir le contact de la classe. Si vous étendez simplement ArrayList, il pourrait ne pas toujours être utilisé comme vous l'avez voulu. Bien sûr, le compromis est que vous devrez créer explicitement des méthodes de passage pour tout ce que vous souhaitez autoriser. Alternativement (ou en outre), vous voudrez peut-être fournir une méthode pour obtenir la liste sous-jacente, que vous pourriez envelopper avec une collection immuable pour la protéger des changements qui se produisent en dehors du contrôle de votre classe.


2 commentaires

J'ai voté parce que c'est la même réponse que Abiusx, que j'ai accepté. Je pouvais accepter les deux :)


Merci. Il a répondu en premier :) bonne question cependant, +1 de moi.



1
votes

@ABIUSX est juste il y a un compromis. Mais j'ai ASollution pour votre souci avec la première approche. S'il vous plaît considérer les suivants et laissez-moi savoir quels problèmes sont avec cette approche:

public class MyClass implements List
{
    private String name;
    private List myList = new ArrayList();

    public MyClass(String name)
    {
        this.name = name;
    }

    public String getName()
    {
        return name;
    }

    public void setName()
    {
        return name;
    }

    @Override
    public void add(int index, Object element)
    {
        myList.add(index,element);
    }

    @Override
    public boolean add(Object o)
    {
        myList.add(o);
    }

    @Override
    public boolean addAll(Collection c)
    {
        myList.addAll(c);
    }

    //so on for rest of methods in List interface
}


0 commentaires

0
votes

héritage arraylist n'est pas une bonne idée, vous avez besoin d'une raison forte de le faire. Les classes utilitaires comme les collections fournissent la fonctionnalité nécessaire dans plusieurs arômes, vous devez donc avoir vraiment besoin d'ajouter des fonctionnalités requises supplémentaires afin de justifier le sous-classement, tout comme une classe très bien connue.


0 commentaires

3
votes

Pour le meilleur des deux mondes, utilisez un GUAVA autoroute . Voici un exemple simple:

public class NamedList<E> extends ForwardingList<E> implements RandomAccess {
  // could also let the user provide the delegate list
  private final List<E> delegate = Lists.newArrayList();
  private String name;

  @Override protected List<E> delegate() {
    return delegate;
  }

  // constructors, getter, setter
}


3 commentaires

Merci, mais ma question est plus théorique / philosophique - je veux connaître les avantages et les inconvénients entre les deux approches. Je ne cherche pas de solutions plus compliquées.


@ red.octobre: ​​Je vois cela comme une solution plus simple. En tout état de cause, écrire votre propre liste de renvoi est suffisamment facile et est l'approche recommandée.


Je ne suis pas sûr que je suis d'accord - cela ne semble plus simple que parce que vous tirez parti du code existant. La transmissionnaire est essentiellement la 2e approche - une classe avec une bande de fonctions "passaire".