2017-10-02 3 views
0

J'ai une conception avec les classes suivantes:conseils de conception de classe (mettre en œuvre avec Java) - ENUM + héritage

public class Book { 
    protected BookColorType color; 
    public Book (BookColorType color) { 
    ... 
    } 
} 

public enum BookColorType { 
    BLACK, WHITE 
} 

public enum ColorBookColorType { 
    BLACK, WHITE, RED, BLUE, GREEN 
} 

public class ColorBook extends Book { 
    protected ColorBookColorType color; 
    public ColorBook(ColorBookColorType color) { 
    // this will cause error has ColorBookColorType is not the same type as BookColorType 
    } 
} 

Comment puis-je mettre en œuvre ce qui précède avec Java et avec une meilleure conception de classe? Le point est que Book doit s'associer uniquement à BookColorType lorsque ColorBook (est un livre) et associer uniquement à ColorBookColorType (avec duplication BLACK et WHITE).

S'il vous plaît aviser, merci.

+0

Ce qui fait '' un ColorBook' Book' dans ce cas? Ce qui est suspect selon vous avec la mise en œuvre actuelle? – nullpointer

+0

Vous avez déjà fourni une implémentation Java, alors quelle est votre question ici? En ce qui concerne le design: il pourrait être préférable de faire de Book une interface ou une classe abstraite et une autre implémentation/sous-classe comme 'NonColoredBook'. Mon problème est que je ne peux pas imaginer ce que la couleur indiquerait ici, c'est-à-dire de quelle manière un livre NOIR serait différent d'un livre BLANC. Vous voulez élaborer? – Thomas

+0

Semble comme un mauvais design et une mauvaise utilisation de l'héritage pour moi. – duffymo

Répondre

0

Si chaque type de Book doit avoir son propre numéro de couleur Type, assurez-vous que chaque classe connaît uniquement le type de couleur dont il a besoin.
Donc, ne faites pas BookColorType color; un champ hérité de la classe Book mais un champ privé de celui-ci et faites ColorBook avoir son propre champ de type de couleur privée: ColorBookColorType color;. En outre, s'il est logique de récupérer une valeur (chaîne ou valeur enum commune ou autre chose) des deux classes enum pour les rendre interopérables d'une certaine manière, vous pouvez leur faire implémenter une interface spécifique.

0

est ici une idée:

  • Vous pourriez avoir à la fois vos énumérations implémenter une interface, par exemple BookColorType.
  • Vous pouvez ensuite renommer votre position actuelle BookColorType ENUM à quelque chose comme BWBookColorType
  • Votre Book classe super maintient le constructeur et prend un objet BookColorType en tant que paramètre
  • constructeur de l » Votre ColorBook invoque super(...)
  • Il peut alors lancer une IllegalArgumentException si le type réel de l'argument n'est pas ColorBookColorType
  • Notez que votre classe ColorBook n'aura pas son propre champ, mais réutilisera le champ de Book, qui sera de type BookColorType (du type de l'interface)

Exemple

public class Book { 
    protected BookColorType color; 

    public Book(BookColorType color) { 

    } 
} 

public interface BookColorType {} 

public enum BWBookColorType implements BookColorType { 
    BLACK, WHITE 
} 

public enum ColorBookColorType implements BookColorType { 
    BLACK, WHITE, RED, BLUE, GREEN 
} 

public class ColorBook extends Book { 

    public ColorBook(BookColorType color) { 
     super(color); // need to be 1st line 
     if (!(color instanceof ColorBookColorType)) { 
      throw new IllegalArgumentException("Only colored books!"); 
     } 
    } 

} 
+0

'(color instanceof ColorBookColorType)' C'est assez moche et peut être résolu avec une autre interface. – Oleg

+1

@Oleg Je suis un peu troublé par votre commentaire ... pourriez-vous expliquer pourquoi un contrôle de type est moche, ou particulièrement la partie sur la "résolution avec une autre interface"? – Mena

+0

Avoir une autre interface 'interface BookColorTypeColor extends BookColorType {}' l'énumération de couleurs peut l'implémenter et le constructeur de colorbook l'a comme paramètre, de cette façon vous n'avez besoin d'aucune vérification de type. Quant à savoir pourquoi c'est vraiment moche ?! Les vérifications de type sont de dernier recours si cela ne vous dérange pas, utilisez juste Object pour tout et remplissez votre code avec des vérifications de type. – Oleg

0

La clé est d'exprimer la contrainte de typage fort, au lieu des contrôles d'exécution idiomatiques comme instanceof.

public interface Book { 
    BookColor getColor(); 
} 

public interface BookColor { 

} 

public enum MonoChrome implements BookColor { 
    BLACK, WHITE 
} 

public enum Colorful implements BookColor { 
    RED, BLUE, GREEN 
} 

public final class ColorBook implements Book { 
    private final Color color; 

    public ColorBook(final BookColor color) { 
     super(); 
     this.color = Objects.requireNonNull(color); 
    } 
} 

public final class MonoChromeBook implements Book { 
    private final Color color; 

    public ColorBook(final MonoChrome color) { 
     super(); 
     this.color = Objects.requireNonNull(color); 
    } 
} 

De cette façon, ColorBook peut avoir à la fois MONOCHROME et que la couleur en couleurs. MonoChromeBook accepte uniquement MonoChrome couleur.

0

appuyant sur @ poste de Mena, j'utiliser Génériques pour appliquer le type de couleur:

public interface BookColorType {} 

public class Book<C extends BookColorType> { 
    protected C color; 

    public Book(C color) { 

    } 
} 

public enum BWBookColorType implements BookColorType { 
    BLACK, WHITE 
} 

public enum ColorBookColorType implements BookColorType { 
    BLACK, WHITE, RED, BLUE, GREEN 
} 

public class ColorBook extends Book<ColorBookColorType> { 
    public ColorBook(ColorBookColorType color) { 
     super(color); 
    } 
} 

public class BWBook extends Book<BWBookColorType> { 
    public BWBook(BWBookColorType color) { 
     super(color); 
    } 
}