C # – Que dois-je utiliser, une interface, une classe abstraite ou les deux?

Donc, hypothétiquement, je construis une sorte d’application immobilière en C #. Pour chaque type de propriété, je vais créer une classe telle que ResidentialProperty et CommercialProperty. Ces deux classes, ainsi que toutes les autres classes de propriétés, partagent certaines propriétés communes, telles que les informations Id, Titre, Description et Adresse.

Ce que j’aimerais pouvoir faire, c’est:
a) renvoyer une collection d’objects contenant uniquement les informations de base
b) être en mesure d’appeler une méthode telle que GetProperty (id) qui créera et retournera un ResidentialProperty ou un CommercialProperty, ou appellera GetProperties () qui retournera une collection de l’un ou de l’autre, ou les deux.

Cela dit, il serait probablement logique de créer une classe abstraite appelée BasicProperty (ou PropertyBase) qui contient tous les atsortingbuts communs, et qui étend les propriétés ResidentialProperty et CommercialProperty. Cela réglerait le problème n ° 1, car je pourrais créer une méthode qui renvoie une collection de propriétés de base.

Mais pour n ° 2, pouvoir retourner l’un ou l’autre type de propriété, il me faudrait une interface (IProperty), les classes résidentielle et commerciale en hériteront, puis les valeurs GetProperty (id) et GetProperties (). un object IProperty (ou parce qu’ils héritent d’IProperty, puis-je les renvoyer en l’état et non en tant qu’Interface?)?

Maintenant, si je dois utiliser une interface, que dois-je faire avec la classe BasicProperty?
– Est-ce que je le laisse comme résumé et implémente l’interface? Ou
– Est-ce que je le laisse en tant qu’abrégé et les 3 classes implémentent l’interface? Ou
– Est-ce que je ne le crée pas sous forme abstraite, je mets toutes les informations de base dans l’interface et les propriétés BasicProperty, ResidentialProperty et CommercialProperty implémentent toutes l’interface?

Merci d’avance, Carl J.

D’après ce que je peux comprendre, vous parlez de deux choses différentes ici.

  1. Structure de classe
  2. Accès aux données de ces classes

Vous avez raison de penser que vous devriez créer une classe abstraite contenant les propriétés communes, c’est ce que l’inheritance est pour 🙂 (entre autres)

Mais je ne vois pas pourquoi vous ne pouvez pas créer une classe d’access aux données qui a une méthode GetProperty(id) qui spécifie un type de retour de PropertyBase

c’est à dire

public PropertyBase GetProperty(long id)

dans l’implémentation de GetProperty vous pouvez GetProperty un object ResidentialProperty ou CommercialProperty (en fonction de la logique métier / firebase database que vous souhaitez), puis le renvoyer, c # vous permet de le faire.

Peut-être que je vous ai mal compris?

HTH

MODIFIER::

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(ssortingng[] args) { } } class DataAccessLayer { public PropertyBase GetSomething(int id) { if (id > 10) return new CommercialProperty(); else return new ResidentialProperty(); } } class PropertyBase { } class ResidentialProperty : PropertyBase { } class CommercialProperty : PropertyBase { } } 

Même si j’estime que définir une interface pour commencer est presque toujours une bonne idée, juste parce que cela aide votre code à être flexible à l’avenir, il semble que dans ce cas, vous n’avez pas réellement besoin de le faire. Vos méthodes GetProperty et GetProperties peuvent utiliser votre classe de base abstraite comme valeur de retour.

Pensez-y comme ceci: Et si j’avais une méthode appelée GetShape ? Cela retournerait probablement une Shape , non? Disons que Shape est une classe de base abstraite et que certaines classes dérivées sont Triangle , Square , Circle , etc.

Mais un sortingangle est une forme, un carré est une forme, et ainsi de suite. Chacune d’elles est plus qu’une forme, mais c’est quand même une forme. Donc, si je dis “donnez-moi une forme” et que vous me donnez un carré, vous ferez comme j’ai demandé. Aucune activité amusante là-bas.

C’est l’un des principes fondamentaux qui sous-tendent la programmation orientée object: une instance d’une classe dérivée est une instance de sa classe de base; c’est juste aussi plus que ça.

Une classe abstraite est utilisée pour fournir un comportement commun. Une interface est utilisée pour fournir un ensemble spécifique de méthodes et de propriétés, quel que soit leur comportement.

Si vos propriétés ResidentialProperty et CommercialProperty présentent un comportement commun, il est probablement logique d’implémenter ce comportement dans une classe abstraite et de faire en sorte qu’elles héritent chacune de cette classe. On peut supposer qu’ils auront également un comportement personnalisé, sinon il n’est pas nécessaire de créer une sous-classe. Il suffit alors simplement d’avoir une propriété PropertyType pour décrire le type de propriété de l’instance.

Vous pouvez ensuite fournir autant d’interfaces que vous jugerez utiles, IPropertyBase, IResidentialProperty et / ou ICommercialProperty. Cela dépend vraiment de savoir si vous attendez de cette bibliothèque une base pour d’autres implémentations pouvant avoir la même interface qu’une ou plusieurs de vos classes, mais pas le même comportement que votre classe abstraite de base. L’autre avantage d’exposer des interfaces qui représentent vos types est la possibilité de se moquer plus facilement des tests unitaires.

Il n’est pas vraiment possible de répondre à cette question de façon absolue, car cela dépend vraiment de la manière dont vos objects sont susceptibles d’être utilisés, mais j’espère que cette réponse vous fournira un guide utile.

À mon avis, vous devriez éviter d’utiliser des classes abstraites à moins que cela ne soit absolument logique.

Une grande partie du comportement courant peut être atsortingbuée à vos entités par agrégation, en utilisant des composants et vous pouvez publier ce comportement en utilisant des interfaces.

La raison pour laquelle j’ai tendance à suivre cette voie, c’est qu’une fois que vous avez une classe de base abstraite, vous êtes obligé de l’utiliser, car vous ne pouvez pas avoir plusieurs inheritances.

Tôt ou tard, vous vous retrouvez avec une situation dans laquelle vous ne voulez pas d’inheritance multiple et vous êtes foutu.

Non pas que je sois un dur sur ce sujet, car bon nombre de nos bases de code utilisent des classes abstraites de base pour ce qui précède, mais celles-ci implémentent les interfaces et tout le code utilisé pour ces classes leur parle à travers les interfaces, afin que nous puissions passer les classes de base pour quelque chose de plus flexible plus tard si nécessaire.

Un rapide pas sur la différence que je vois. Vous pouvez toujours utiliser une classe de base abstraite même lorsque vous implémentez des interfaces. Les interfaces ne vous aident pas à éviter la duplication de code que vous devriez (voir le principe de DRY ), mais cela ne vous oblige pas à dériver de quoi que ce soit de spécial qui les rend plus faciles à combiner avec d’autres classes de base ou interfaces.

D’autre part, une classe de base abstraite peut supprimer certaines duplications et il est plus facile de modifier certaines choses de la base sans toucher aux classes dérivées. Ce dernier est très pratique lorsque vous implémentez une bibliothèque de classes que d’autres utilisent. Si vous modifiez des éléments d’interface dans une bibliothèque, toutes les implémentations de cette interface doivent être modifiées! Cela pourrait être un très petit problème si vous implémentez une application uniquement avec un petit groupe de développeurs. Mais comme d’autres l’ont dit, une classe de base vous oblige à en dériver et vous ne pouvez pas dériver de quelque chose d’autre si ce besoin apparaît.

N’appelez pas votre classe de base ou votre interface BasicProperty ou PropertyBase, appelez-la simplement Property. Vous n’aurez pas à la fois une propriété et une propriété de base, voulez-vous? Vous allez agir avec des classes de propriétés ou des interfaces.

Une classe abstraite est presque identique à une interface, à la différence que la classe abstraite peut stocker un état dans des variables de champ. Une façon de le faire est de disposer de données telles que l’adresse stockée, une classe abstraite avec un champ.

Maintenant, le sous-groupe d’une classe est l’un des exemples d’OOD de livre d’images, mais il existe d’autres moyens de différencier les objects que celui-ci: regardez le décorateur et les modèles de comportement. Vous ne devez sous-classer que si vous devez redéfinir les méthodes de la classe de base. Regardez ceci par exemple.