73 votes

Des bons exemples d'héritage d'une classe concrète?

Arrière-plan:

En tant que programmeur Java, j'ai largement l'héritage (plutôt: mettre en œuvre) des interfaces, et parfois j'conception de classes de base abstraites. Cependant, je n'ai jamais vraiment ressenti le besoin de sous-classe concrète (non abrégé) de la classe (dans le cas où je le faisais, il s'est avéré plus tard qu'une autre solution, comme la délégation aurait été mieux).

Donc, maintenant, je commence à sentir qu'il n'y a presque pas de situation où l'héritage d'une classe concrète est approprié. Pour une chose, le principe de substitution de Liskov (LSP) semble presque impossible à satisfaire pour les non-trivial classes; également de nombreuses autres questions ici, semblent faire l'écho d'une opinion similaire.

Donc ma question:

Dans quelle situation (le cas échéant) est-elle vraiment un sens pour hériter d'une classe concrète? Pouvez-vous donner un béton, dans le monde réel exemple d'une classe qui hérite d'une autre classe de béton, où vous pensez que c'est la meilleure conception en tenant compte des contraintes? J'ai b'être particulièrement intéressés par les exemples qui répondent à la LSP (ou des exemples où la satisfaction LSP semble sans importance).

J'ai surtout un Java arrière-plan, mais je suis intéressé par des exemples à partir de n'importe quelle langue.

20voto

DaveFar Points 3360

Vous avez souvent un squelette implémentations de l'interface I. Si vous pouvez offrir une extensibilité sans méthodes abstraites (par exemple, via les hooks), il est préférable d'avoir un non-abstraite squelettique de classe parce que vous pouvez l'instancier.

Un exemple serait un transfert des classes wrapper, pour être en mesure de transmettre à un autre objet de la classe de béton C œuvre I, par exemple, l'activation de la décoration ou de simple de réutiliser le code de l' C sans avoir à hériter de la C. Vous pouvez trouver un tel exemple dans Efficace Java article 16, à la faveur de la composition au cours de l'héritage. (Je ne veux pas le poster ici parce que du droit d'auteur, mais il est vraiment tout simplement renvoi de tous les appels de méthode de I de la enveloppé de mise en œuvre).

18voto

Andrey Points 2962

Je pense que ce qui suit est un bon exemple lorsqu’il peut être approprié :

Un autre bon exemple est l’héritage d’exceptions :

14voto

KeithS Points 36130

Un cas très commun, je peux penser à est de dériver de base des contrôles d'INTERFACE utilisateur, tels que des formulaires, des zones de texte, zones de liste modifiables, etc. Ils sont au complet, concret, et bien capable de se tenir debout sur leur propre; cependant, la plupart d'entre eux sont également très basique, et parfois leur comportement par défaut n'est pas ce que vous voulez. Quasiment personne, par exemple, serait d'utiliser une instance de pure Forme, à moins que peut-être ils ont été la création d'un tout dynamique de la couche d'INTERFACE utilisateur.

Par exemple, dans un morceau de logiciel que j'ai écrit qui a récemment atteint la maturité relative (sens j'ai manqué de temps pour se concentrer principalement sur le développement d'elle :) ), j'ai trouvé j'ai besoin d'ajouter "lazy loading" capacité de zones de liste modifiables, donc il ne serait pas prendre 50 ans (en ordinateur ans) pour la première fenêtre à charger. J'ai aussi besoin de la capacité de filtrer automatiquement les options disponibles dans une zone de liste déroulante basée sur ce qui a été montré dans un autre, et enfin, j'ai besoin d'un moyen de "miroir" d'une zone de liste déroulante de la valeur dans un autre modifiable de contrôle, et de faire un changement dans le contrôle d'arriver à l'autre. Donc, j'ai étendu la base ComboBox pour lui donner ces fonctionnalités supplémentaires, et a créé deux nouveaux types: LazyComboBox, et puis d'autres, MirroringComboBox. Les deux sont basés sur le totalement utilisable, béton contrôle zone de liste déroulante, juste primordial certains comportements et d'ajouter quelques autres. Ils ne sont pas très faiblement couplée, et donc de ne pas trop SOLIDE, mais la fonctionnalité est suffisamment générique que si j'en avais, je pourrais réécrire l'une de ces classes à partir de zéro pour faire le même travail, peut-être mieux.

12voto

S.L. Barth Points 4203

De manière générale, la seule fois où que j’ai dérivent de classes concrètes est quand ils sont dans le cadre. Dérivant de ou étant l’exemple trivial.

7voto

Buhake Sindi Points 38654

Ceci est un exemple d'une application actuelle je suis en entreprise.

Dans OAuth 2 de l'environnement, étant donné que la documentation est encore au stade de projet, le cahier des charges ne cesse de changer (au moment de la rédaction, nous sommes dans la version 21).

Ainsi, j'ai dû prolonger mon béton AccessToken classe pour accueillir les différents jetons d'accès.

Dans le précédent projet, il n'y avait pas token_type ensemble sur le terrain, de sorte que le réel jeton d'accès est comme suit:

public class AccessToken extends OAuthToken {

    /**
     * 
     */
    private static final long serialVersionUID = -4419729971477912556L;
    private String accessToken;
    private String refreshToken;
    private Map<String, String> additionalParameters;

    //Getters and setters are here
}

Maintenant, avec les jetons d'Accès que les retours token_type,, j'ai

public class TokenTypedAccessToken extends AccessToken {

    private String tokenType;
    //Getter and setter are here...
}

Donc, je peux la retourner et l'utilisateur final n'est pas plus sage. :-)

En Résumé: Si vous souhaitez personnaliser une classe qui a la même fonctionnalité de votre classe de béton sans modifier la structure de la classe concrète, je suggère d'étendre la classe concrète.

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