2010-06-04 5 views
1

Lors de la création d'une hiérarchie d'héritage, je suis confus. La classe de base abstraite ne doit contenir que des éléments couramment utilisés pour les classes héritées. Mais savoir quelles méthodes, champs et propriétés sont couramment utilisés n'est pas possible lors de la conception. Je me sens donc libre de les grouper avec des classes abstraites qui héritent hiérarchiquement. C'est ce que je fais sans souci sur lequel mes vraies classes seront hiérarchisées car je trouverai facilement une place dans la hiérarchie globale. Et il est également possible de trouver des classes abstraites inutiles au milieu de la hiérarchie.Questions lors de la conception de la hiérarchie OOP

Mais je ne sais pas est-ce une bonne façon de concevoir? Et quels désavantages peuvent se produire dans une hiérarchie abstraite non parfaite. Je dois donner un exemple clair pour cela. Pensez aux échecs et aux pièces. Si je dois définir des pièces comme pion, reine, roi, etc. Regardez ci-dessous diagramme UML.

http://i.stack.imgur.com/1VC22.png

Je divisé hierarcy à 2 pièces et glissés aucun-après Piece glissés classe abstraite parce que je crois que le glissement et aucun coulissant exigera différents membres couramment utilisés.

Mais je peux aussi les diviser de manière directionnelle car certaines pièces peuvent aller dans 8 directions, certaines dans 4 directions et d'autres dans 2 ou 3 directions. Les regrouper de manière directionnelle provoque de nouvelles questions. Où ils seront dans la hiérarchie? ils viendront après des classes glissantes? Si possible de trouver quatre groupes directionnels sous des groupes glissant et aucun-glissant et nous savons qu'il n'est pas possible d'hériter par 2 classes. Donc, pour de telles situations, je dois choisir des interfaces? si les directions ne seront jamais sous les deux, il est donc possible d'utiliser des classes abstraites. Ce n'est pas grave si je retrouvais un nouveau groupement commun qui ne nécessiterait pas l'héritage de 2 classes donc je peux le définir sous directions. En fin de conception, toutes mes pièces peuvent trouver des nœuds feuilles parfaits dans la hiérarchie et ce sera vraiment bon pour l'avenir d'avoir assez de construction complète dont je n'aurai pas besoin de changer quelque chose dans la hiérarchie.

Mais quel peut être l'inconvénient de créer une hiérarchie globale trop importante? Peut-être que dans auto-complète de l'IDE peut montrer beaucoup de classes de base abstraite nommées inutiles et étranges qui confondent les autres? quels peuvent être d'autres inconvénients?

+0

Sérieusement? Cela semble * trop * compliqué. –

Répondre

2

Way, beaucoup trop compliqué pour la tâche. Vous exagérez le OO. Cela signifie que vous devrez remplir 20 classes impaires avec du code. Vous devriez vraiment simplifier cela. Pensez à y penser en termes d'attributs (couleur, isUnderAttack) et de comportement (en mouvement). Dans ce cas, vous n'avez besoin que d'une classe class ChessPiece, qui a des propriétés pour la couleur et isUnderAttack. Vous pouvez ensuite utiliser une forme d'injection de dépendance. Voyez comment ce code ressemblerait:

public class ChessPiece 
{ 
    public enum ChessPieceColor{White, Black} 
    private IChessMove behavior; 
    public ChessPiece(IChessMove behavior, ChessPieceColor color) 
    { 
     this.behavior = behavior; 
    } 
    public void Move() 
    { 
     behavior.Move(); 
    } 
} 

public interface IChessMove 
{ 
    void Move(); 
} 

public class KnightMove : IChessMove 
{ 
    public void Move() 
    { 
     // code to perform the moving. 
    } 
} 

public class Program 
{ 
    static void Main() 
    { 
     ChessPiece knight = new ChessPiece(new KnightMove(), ChessPiece.ChessPieceColor.White); 
    } 
} 

Ensuite, vous coderez simplement un IChessMove différent pour chaque type de pièce. Évidemment, vous aurez besoin d'ajouter plus d'informations sur les méthodes ici pour le faire fonctionner, mais il devrait vous montrer le modèle que vous devriez utiliser ici. Une classe pour chaque pièce possible va trop loin, quand beaucoup ont des comportements communs.

+0

Oui, on peut utiliser un champ qui contient de la couleur, au lieu de séparer les classes pour les blancs et les noirs. C'est ce que j'ai aussi pensé mais dans mon application la simplification est plus importante pour moi .So séparer les sera vraiment plus utile.Oui, Il est important de définir des méthodes et même ce que je vais faire dans les corps de méthode. Cela peut causer des changements dans hiearcy. Mettre un membre de couleur dans les classes provoquera des vérifications de couleur dans les méthodes et c'est ce que je n'ai pas préféré. – Freshblood

+3

Je ne pense pas que vous compreniez vraiment le but de la POO. Les classes sont utilisées pour séparer le comportement et non les propriétés de l'objet. Un pion blanc ne bouge pas différemment d'un pion noir. C'est simplement une condition qu'ils doivent vérifier quand ils essaient de capturer une pièce. Faire 2 classes pour chaque pièce ne simplifie pas les choses. Cela signifie que vous devez écrire le code de mouvement deux fois pour chaque pièce. De plus, c'est une pente glissante. Qui peut dire que vous ne devriez pas étendre WhitePawn dans des classes appelées WhitePawn1, WhitePawn2, WhitePawn3, etc? Le diagramme actuel est un cauchemar en termes de maintenance. – drharris

+0

Je ne pense pas que je suis loin d'en comprendre le but. Les pions blancs et noirs ont des comportements différents à bord. Mais vous avez raison de dire que toutes les pièces n'ont pas des comportements différents. Par exemple, évêques, reines, chevaliers et Les méthodes d'évaluation que j'ajouterai plus tard nécessiteront des méthodes et des corps de méthode différents. Ainsi, les méthodes de movegeneration ne seront pas écrites deux fois si elles ne sont pas obligatoires. La classe de base aura une action de mouvement commune. – Freshblood

1

Ok ... Le problème est que les hiérarchies héritées sont fragiles - elles peuvent être facilement inutiles, par exemple dans les cas que vous décrivez comme étant vos préoccupations. Vous pouvez concevoir la hiérarchie de plusieurs façons, comme vous le suggérez, mais gardez à l'esprit le principe de substitution de Liskov et, surtout, que vous ne devriez pas abuser de l'héritage. Utilisez-le seulement si nécessaire. Vous ne devriez pas utiliser la classe abstraite et l'héritage juste parce que vous le pouvez.Je ne suis pas bon aux échecs, mais les morceaux de différentes couleurs ont-ils des comportements différents? Il existe un exemple célèbre de problème d'abstraction lors de la création de la hiérarchie d'héritage. Prenez un cercle et une ellipse, ce qui est plus abstrait? Lorsque vous essayez de faire de l'un d'entre eux superclasse de l'autre, vous allez vous retrouver avec un design inflexible. Essayez d'en savoir plus sur la programmation orientée objet et essayez d'hériter seulement quand aucun autre choix n'est meilleur.

+0

couleur des pièces provoquent des comportements différents.nous pouvons vaincre par définir membre qui détient la couleur de la pièce. Mais ce n'est pas ce que je préfère .Pourtant je ne sais pas quel est le désavantage d'une telle façon. Même il semble que cela va simplifier ma Pensez que nous ne définirons que les pièces WhitePawn ou BlackPawn etc, il n'a aucune importance à ce qu'ils sont hérités et comment était la hiérarchie, car toute la hiérarchie est abstraite, sauf de vraies pièces classes. Ai-je raison? – Freshblood

+0

je vais tester les deux façons et aura expérience ce qui est mauvais et bon, mais demander avant d'essayer, il peut être utile et gagner du temps. Déjà mon moteur d'échecs joue aux échecs, mais les pièces ne sont même pas une classe, ils sont définis par entier. aller plus loin dans POO et simplifier les codes plus et avoir des codes qui ne sont pas trop dans les méthodes – Freshblood

1

Mais quel peut être l'inconvénient de créer une hiérarchie globale trop importante?

l'inconvénient d'avoir un modèle trop complexe est que cela rend le code plus difficile à écrire, lire et à entretenir.

Cela arrive cependant. C'est très difficile de concevoir la chose dès le premier coup. C'est mieux de ne pas essayer.

C'est ce à quoi sert le développement piloté par les tests. Plutôt que de faire des hypothèses sur ce dont vous avez besoin, vous utilisez des tests pour étoffer vos exigences qui à leur tour étoffent une mise en œuvre. TDD ftw.

Questions connexes