web-dev-qa-db-fra.com

Quand déplacer un champ commun dans une classe de base?

J'ai actuellement deux classes dérivées, A et B, qui ont toutes deux un champ en commun et j'essaie de déterminer s'il doit remonter dans la classe de base.

Il n'est jamais référencé à partir de la classe de base, et dire si à un moment donné, une autre classe est dérivée, C, qui n'a pas de _field1, alors le principe des "moins privilégiés" (ou quelque chose) ne serait-il pas violé s'il l'était?

public abstract class Base
{
    // Should _field1 be brought up to Base?
    //protected int Field1 { get; set; }
}

public class A : Base
{
    private int _field1;
}

public class B : Base
{
    private int _field1;
}

public class C : Base
{
    // Doesn't have/reference _field1
}
16
samis

Tout dépend du problème exact que vous essayez de résoudre.

Prenons un exemple concret: votre classe de base abstraite est Vehicle et vous disposez actuellement des implémentations concrètes Bicycle et Car. Vous envisagez de déplacer numberOfWheels de Bicycle et Car vers le véhicule. Devriez-vous faire ça? Non! Parce que tous les véhicules n'ont pas de roues. Vous pouvez déjà dire que si vous essayez d'ajouter une classe Boat, cela va se casser.

Maintenant, si votre classe de base abstraite était WheeledVehicle, il est logique d'avoir la variable membre numberOfWheels dedans.

Vous devez appliquer la même logique à votre problème, car comme vous pouvez le voir, ce n'est pas une simple réponse oui ou non.

34
Pete

Logiquement, au-delà de placer le champ répliqué dans des sous-classes vs en commun dans la classe de base, il y a une troisième option: introduire une nouvelle sous-classe dans la hiérarchie qui a les propriétés communes entre les deux. @Pete y fait allusion sans y aller complètement.

En utilisant l'exemple de @ Pete, nous introduirions une sous-classe (éventuellement abstraite) pour les véhicules à roues qui descend de la classe de base d'origine - tandis que les deux sous-classes en descendent. Ainsi, la classe de base d'origine n'est pas polluée par les roues, mais le point commun des roues est DRY (non répété parmi les sous-classes qui ont des roues).

Bien sûr, cela peut être excessif pour vos besoins, mais cela est pris en charge par le mécanisme de hiérarchie des classes.

13
Erik Eidt

Je vais jouer l'avocat du diable ici.

En ce moment, vous devriez faire rien.

Est-ce SEC? Non. Mais il vaut mieux avoir un peu de duplication qu'une abstraction prématurée dont vous ne pourrez pas facilement vous défaire plus tard. Le refactor pour déplacer une propriété vers une classe de base commune est facile. Aller dans l'autre sens ne l'est pas. Attend et regarde.

En prenant ce genre de décision, j'ai tendance à utiliser une "règle de 3": une fois que j'ai répété la même chose dans par ex. trois endroits différents, et alors seulement, je pense à le déplacer dans la chaîne. N.B. vous n'êtes qu'à 2 ans.

9
Jared Smith

En général, je le déplacerais dans la classe de base. Je ne pense pas qu'il y ait un objectif oui/non, car il y a un compromis ici - porter des champs inutilisés contre réduire la complexité.

Je préfère généralement les classes de base "lourdes" qui contiennent tout ce qui pourrait être partagé. Cela rend la sérialisation vers des fichiers plus simple car vous n'avez pas besoin de méthodes de sérialisation descendantes dans chaque classe dérivée. Mais si vous ne rencontrez pas ce problème ou un problème similaire, ou si vous devez faire tout ce que vous pouvez pour réduire l'utilisation de la mémoire, ne conserver que les champs où vous en avez besoin devrait être correct.

Une classe "intermédiaire" qui présente les champs communs sera très bien si vous avez un nombre très limité de champs. Mais sachez que cette approche peut considérablement augmenter la complexité si vous avez des dizaines de champs utilisés dans différentes combinaisons, conduisant à de nombreuses classes intermédiaires introduisant chacune un ensemble spécifique de champs. Cela peut devenir un problème de maintenance.

2
GrandmasterB