55 votes

Comment peut-interfaces de remplacer la nécessité pour l'héritage multiple quand elles ont des classes existantes

Tout d'abord... Désolé pour ce post. Je sais qu'il y a de nombreux de nombreux messages sur stackoverflow qui sont en train de discuter de l'héritage multiple. Mais je sais déjà que Java ne supporte pas l'héritage multiple, et je sais que l'utilisation de l'interface doit être une alternative. Mais je ne comprends pas et voir mon dilemme:

Je dois faire des modifications sur un très très vaste et très complexe outil écrit en Java. Dans cet outil, il est une structure de données construite avec beaucoup de différents objets de la classe est associé à un membre de la hiérarchie. De toute façon...

  • J'ai une classe Tagged qui a de multiples méthodes et renvoie un objet de la balise en fonction de la classe de l'objet. Il a besoin de membres et de variables statiques.
  • Et une deuxième classe appelée XMLElement permet de lier des objets et à la fin de générer un fichier XML. J'ai aussi besoin de membre et variables statiques ici.
  • Enfin, j'ai ces beaucoup de beaucoup de classes de données dont la quasi-totalité devrait s'étendre XMLElement et certains d'entre eux Tagged.

Ok ok, cela ne fonctionne pas car il n'est possible de prolonger une seule classe. Je lis très souvent que tout ce qui concerne Java est ok et il n'est pas nécessaire d'avoir de l'héritage multiple. Je crois, mais je ne vois pas comment une interface doit remplacer l'héritage.

  1. Il ne fait aucun sens de mettre la réelle mise en œuvre dans toutes les classes de données puisque c'est le même à chaque fois mais ce serait nécessaire, avec des interfaces (je pense).
  2. Je ne vois pas comment je pourrais changer un de mes héritage de classes à une interface. J'ai variables dans ici, et ils ont à être exactement là.

Je n'ai vraiment pas obtenir il plaît quelqu'un peut-il m'expliquer comment gérer cela?

79voto

SouthRoad Points 591

En fait, je n'ai pas de bonne réponse autre que Java DOIT avoir l'Héritage Multiple. Le point de l'ensemble que l'interface doit être en mesure de remplacer la nécessité pour l'Héritage Multiple, c'est comme le gros mensonge que quand il est répété assez de fois devient vrai.

L'argument est que l'Héritage Multiple causes de tous ces problèmes (la-di-dah), pourtant je n'arrête pas d'entendre ces arguments de développeurs Java qui n'ont jamais utilisé le C++. Je n'ai pas TOUJOURS se rappeler les programmeurs en C++ en disant: "Mince, j'aime le C++, mais si ils ne se débarrasser de l'Héritage Multiple, elle serait devenue une grande langue". Les gens utilisés lors de la pratique et n'a pas lorsqu'il n'était pas.

Votre problème est un cas classique où l'Héritage Multiple serait approprié. Toute suggestion de refactoriser le code est vraiment vous dire comment contourner le PROBLÈME est que Java n'a pas d'Héritage Multiple.

Aussi de toutes les discussions que "oh, délégation est mieux, la-di-dah" consiste à confondre la religion avec la conception. Il n'y a pas de bonne façon. Les choses sont plus utiles ou moins utiles, et c'est tout.

Dans votre cas, l'Héritage Multiple serait plus utile et une solution plus élégante.

Aussi loin que la refactorisation de votre code en moins utile à satisfaire à toutes les personnes religieuses qui n'ont jamais utilisé l'Héritage Multiple et de croire à "l'Héritage Multiple est mauvais", je suppose que vous avez à faire un downgrade de votre code, car je ne vois pas en Java "l'amélioration" de cette façon, n'importe quand bientôt. Il y a trop de gens de répéter les religieux mantra au point de la bêtise que je ne peux pas le voir jamais être ajouté à la langue.

En fait, ma solution pour vous serait de la "x s'étend Marqués, XMLElement" et ce serait tout.

...mais comme vous pouvez le voir sur les solutions proposées ci-dessus, la plupart des gens pensent qu'une telle solution serait TROP COMPLEXE ET DÉROUTANT!

Je préfère s'aventurer dans le "x s'étend a,b" territoire de moi-même, même si c'est très effrayant solution qui pourrait submerger les capacités de la plupart des programmeurs Java.

Ce qui est encore plus étonnant, les solutions proposées ci-dessus, c'est que tout le monde ici qui a suggéré que vous refactoriser le code en "délégation" parce que l'Héritage Multiple est mauvais, si ils ont été confrontés au même problème, permettrait de résoudre le problème simplement en faisant: "x s'étend a,b" et être fait avec elle, et tous leurs arguments religieux à propos de "délégation vs héritage" disparaîtrait. Tout le débat est stupide, et il ne avancé par désemparés programmeurs qui n'ont qu'à démontrer à quel point ils peuvent réciter d'un livre et le peu qu'ils peuvent penser par eux-mêmes.

Vous êtes à 100% de réponses correctes que l'Héritage Multiple pourrait l'aider, et non, vous faites quelque chose de mal dans votre code si vous pensez que Java.

58voto

JB Nizet Points 250258

Vous devriez probablement faveur de composition (et délégation) sur l'héritage :

public interface TaggedInterface {
    void foo();
}

public interface XMLElementInterface {
    void bar();
}

public class Tagged implements TaggedInterface {
    // ...
}

public class XMLElement implements XMLElementInterface {
    // ...
}

public class TaggedXmlElement implements TaggedInterface, XMLElementInterface {
    private TaggedInterface tagged;
    private XMLElementInterface xmlElement;

    public TaggedXmlElement(TaggedInterface tagged, XMLElementInterface xmlElement) {
        this.tagged = tagged;
        this.xmlElement = xmlElement;
    }

    public void foo() {
        this.tagged.foo();
    }

    public void bar() {
        this.xmlElement.bar();
    }

    public static void main(String[] args) {
        TaggedXmlElement t = new TaggedXmlElement(new Tagged(), new XMLElement());
        t.foo();
        t.bar();
    }
}

4voto

aioobe Points 158466

D'abord il ne fait pas de sens de mettre la réelle mise en œuvre dans toutes les classes de données puisque c'est le même à chaque fois mais ce serait nécessaire, avec des interfaces (je pense).

Comment sur l'utilisation de l'agrégation pour les tags?

  1. Renommer votre Tagged classe Tags.

  2. Créer un Tagged interface:

    interface Tagged { Tags getTags(); }

  3. Laissez chaque classe qui a besoin d'être "étiqueté", de mettre en oeuvre Tagged et la laisser en tags champ, qui est retourné à partir de getTags.

La deuxième je ne vois pas comment je pourrais changer un de mes héritage de classes à une interface. J'ai variables dans ici, et ils ont à être exactement là.

C'est vrai, les interfaces ne peuvent pas avoir les variables d'instance. Les structures de données stockant les balises cependant, ne devrait pas nécessairement de l'OMI faire partie des classes qui sont marqués. Facteur les balises dans une structure de données distincte.

2voto

Andreas_D Points 64111

J'aimerais le résoudre de cette façon: extrait des interfaces pour l' Tagged et XMLElement classe (peut-être que vous n'avez pas besoin de toutes les méthodes dans l'interface publique). Ensuite, mettre en œuvre des interfaces et de la mise en œuvre de la classe a un Tagged (votre concrètes Tagged de la classe) et un XMLElement (votre concrètes XMLElement de la classe):

 public class MyClass implements Tagged, XMLElement {

    private Tagged tagged;
    private XMLElement xmlElement;

    public MyClass(/*...*/) {
      tagged = new TaggedImpl();
      xmlElement = new XMLElementImpl();
    }

    @Override
    public void someTaggedMethod() {
      tagged.someTaggedMethod();
    }
  }

  public class TaggedImpl implements Tagged {
    @Override
    public void someTaggedMethod() {
      // so what has to be done
    }
  }

  public interface Tagged {
     public void someTaggedMethod();
  }

(et de même pour XMLElement)

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