Quelles sont les différences entre les classes abstraites, les interfaces et quand les utiliser

15

Récemment, j'ai commencé à faire le tour de la POO et je suis maintenant au point où plus je lis sur les différences entre les classes abstraites et les interfaces, plus je deviens confus. Jusqu'à présent, aucun des deux ne peut être instancié. Les interfaces sont des plans plus ou moins structurels qui déterminent le squelette et les résumés sont différents en pouvant implémenter partiellement du code.

J'aimerais en savoir plus à ce sujet à travers ma situation particulière. Voici un lien vers ma première question si vous souhaitez un peu plus d'informations générales: Qu'est-ce qu'un bon modèle de conception pour ma nouvelle classe?

Voici deux classes que j'ai créées:

class Ad {
    $title;
    $description
    $price;

    function get_data($website){  }

    function validate_price(){  }
 }


class calendar_event {
    $title;
    $description

    $start_date;

    function get_data($website){ //guts }

    function validate_dates(){ //guts }
 }

Donc, comme vous pouvez le voir, ces classes sont presque identiques. Non illustré ici, mais il existe d'autres fonctions like get_zip(), save_to_database()qui sont communes à toutes mes classes. J'ai également ajouté d'autres classes Cars and Pets qui ont toutes les méthodes communes et bien sûr des propriétés spécifiques à ces classes (kilométrage, poids, par exemple).

Maintenant, j'ai violé le principe DRY et je gère et modifie le même code sur plusieurs fichiers. J'ai l'intention d'avoir plus de cours comme des bateaux, des chevaux ou autre chose.

Est-ce donc là que j'utiliserais une interface ou une classe abstraite? D'après ce que je comprends des classes abstraites, j'utiliserais une super classe comme modèle avec tous les éléments communs intégrés dans la classe abstraite, puis j'ajouterais uniquement les éléments spécifiquement nécessaires dans les futures classes. Par exemple:

abstract class content {
    $title;
    $description


    function get_data($website){  }

    function common_function2() { }
    function common_function3() { }
 }


class calendar_event extends content {

    $start_date;

    function validate_dates(){  }
 }

Ou devrais-je utiliser une interface et, parce qu'elles sont si similaires, créer une structure que chacune des sous-classes est obligée d'utiliser pour des raisons d'intégrité, et laisser le soin au développeur final qui étoffe cette classe d'être responsable de chacun des détails même des fonctions communes. ma pensée est que certaines fonctions «communes» devront peut-être être modifiées à l'avenir pour les besoins de leur classe spécifique.

Malgré tout ce qui précède, si vous croyez que je comprends mal le quoi et le pourquoi des classes abstraites et des interfaces, laissez par tous les moyens une réponse valable cesser de penser dans cette direction et suggérer la bonne façon d'aller de l'avant!

Merci!

user66662
la source
Il y a beaucoup de bons exemples en ligne. Je pense que c'est l'un d'entre eux. javapapers.com/core-java/abstract-and-interface-core-java-2/…
Siva

Réponses:

26

En termes simples:

Les interfaces sont pour le type de relations «peuvent faire / peuvent être traitées» .

Les classes abstraites (ainsi que concrètes) sont destinées à "est une" sorte de relation.

Regardez ces exemples:

class Bird extends Animal implements Flight;
class Plane extends Vehicle implements Flight, AccountableAsset;
class Mosquito extends Animal implements Flight;
class Horse extends Animal;
class RaceHorse extends Horse implements AccountableAsset;
class Pegasus extends Horse implements Flight;

Bird, Mosquitoet le Horse sont Animals . Ils sont reliés. Ils héritent des méthodes communes d'Animal like eat(), metabolize() and reproduce(). Peut-être qu'ils remplacent ces méthodes, en y ajoutant un peu plus, mais ils profitent du comportement par défaut implémenté dans Animal commemetabolizeGlucose().

Planen'est pas lié à Bird, Mosquitoou Horse.

Flightest implémenté par des classes différentes et non apparentées, comme Birdet Plane.

AccountableAssetest également implémenté par des classes différentes et non apparentées, comme Planeet RaceHorse.

Horse n'implémente pas Flight.

Comme vous pouvez le voir, les classes (abstraites ou concrètes) vous aident à créer des hiérarchies , vous permettant d'hériter du code des niveaux supérieurs aux niveaux inférieurs de la hiérarchie. En théorie, plus vous êtes bas dans la hiérarchie, plus votre comportement est spécialisé, mais vous n'avez pas à vous soucier de beaucoup de choses qui sont déjà prises en charge.

Les interfaces , en revanche, ne créent aucune hiérarchie, mais elles peuvent aider à homogénéiser certains comportements entre les hiérarchies afin que vous puissiez les soustraire de la hiérarchie dans certains contextes.

Par exemple, vous pouvez avoir un programme additionnant la valeur d'un groupe de AccountableAssetsindépendamment de leur être RaceHorsesou Planes.

Tulains Córdova
la source
Incroyable. L'interface fournit une certaine section de fonctionnalité qui impose can do/can be treated asoù les classes abstraites agissent comme fondamentales!
Abhiroj Panwar
13

Vous pouvez en déduire la réponse logiquement car vous semblez être au courant des différences entre les deux.

Les interfaces définissent un contrat commun. Comme une interface appelée IAnimal, où tous les animaux partagent des fonctions telles que Eat (), Move (), Attack () etc. il.

Les classes abstraites définissent une implémentation commune et éventuellement des contrats communs. Par exemple, une calculatrice simple peut être considérée comme une classe abstraite qui implémente tous les opérateurs logiques et au niveau du bit de base, puis est étendue par ScientificCalculator, GraphicalCalculator, etc.

Si vous avez une implémentation commune, par tous les moyens, encapsulez la fonctionnalité dans une classe abstraite à partir de laquelle étendre. J'ai une expérience PHP proche de 0, mais je ne pense pas que vous puissiez créer des interfaces avec des champs non constants. Si les champs sont communs à vos classes d'instance, vous êtes obligé d'utiliser une classe abstraite, sauf si vous définissez l'accès à ces dernières via des getters et des setters.

De plus, il ne semble pas y avoir de pénurie de résultats dans Google.

Dante
la source
3

Longue histoire courte. Les classes abstraites ressemblent beaucoup aux interfaces dans la mesure où elles fournissent toutes les deux un modèle de quelles méthodes devraient être au sein de la classe héritière, mais il y a de grandes différences: - Les interfaces définissent uniquement les noms / types de méthodes qui doivent exister dans une classe héritée, tandis que les classes peuvent avoir un code de méthode par défaut complet et il suffit de remplacer les détails. - Les interfaces ne peuvent pas avoir de modificateurs d'accès. - Les interfaces ne peuvent pas avoir de champs. - Les classes ne peuvent pas avoir plusieurs héritages de classes, alors qu'elles peuvent hériter de plusieurs interfaces. - De plus, les classes fournissent une structure hiérarchique de sorte que seules les classes dérivées d'une classe spécifique doivent suivre les directives de la classe abstraite: objet-> objet spécifique-> objet très spécifique. D'un autre côté, les interfaces peuvent être héritées par n'importe qui.

À mon avis, les classes abstraites sont plus courantes dans la mesure où elles peuvent fournir une implémentation par défaut du code immédiatement, mais dans les projets à grande échelle où vous devez standardiser certaines classes, les interfaces peuvent être utiles.

J'espère que ça aide, mais il y a beaucoup d'informations sur ce site en ligne, Leo

RealityDysfunction
la source
2
Classes cannot have multiple inheritance- Vrai pour les langages comme Java et C #, pas vrai pour C ++.
Robert Harvey
3

Tout d'abord, vous devez comprendre que vous fournissez souvent à la fois une interface et une classe abstraite. La raison de cela, et la principale différence entre les deux, est qu'ils vous permettent de réutiliser un code différent et donc de résoudre différents problèmes.

Les interfaces vous permettent de réutiliser le code client avec différentes implémentations. Un client de votre classe get_data ($ website) ne se soucie pas des éléments $ title ou $ description. Il veut juste demander à votre contenu de charger les données. Si vous avez différents types de contenu, dont certains nécessitent une description $ et d'autres non, vous pouvez fournir une classe ContentInterface qui spécifie uniquement la signature de vos classes enfants. Maintenant, le client peut avoir un nombre illimité de contenus différents sans que chacun sache exactement comment ils fonctionnent. Le principe de substitution de Liskov est une bonne chose à lire pour étudier cette idée. J'aime aussi l' écriture de l' oncle Bob sur le sujet. Les interfaces sont très importantes pour les tests unitaires, et la création d'interfaces est une bonne habitude à apprendre.

Les classes abstraites vous permettent de réutiliser les détails d'implémentation communs à travers un ensemble de classes qui partagent un ancêtre commun. Dans votre question, vous semblez bien comprendre pourquoi vous héritez de l'implémentation d'une classe abstraite. Il est toujours dangereux de dépendre des éléments internes d'une classe de base - il est très facile de violer l'encapsulation et de créer des enfants qui dépendent des détails d'implémentation spécifiques d'une classe de base. Le modèle de méthode de modèle fournit un exemple courant et sain d'utilisation des classes de base sans violer l'encapsulation.

Donc, comme j'espère l'avoir montré, vous fournissez souvent des interfaces pour les clients de votre hiérarchie de classe, afin de pouvoir modifier votre implémentation en toute sécurité sans impact sur le code client. Cela permet au client d'écrire des tests unitaires en utilisant des objets fantômes qui héritent de votre interface. Et vous fournirez également des classes abstraites qui permettent de réutiliser la logique commune ou d'appliquer la sémantique pour les classes enfants.

Ben
la source
3

La différence est subtile mais claire. L'interface concerne le comportement polymorphe. La classe abstraite concerne la réutilisation et le comportement polymorphe.

Si vous souhaitez mettre l'accent sur la réutilisation et le comportement polymorphe, choisissez la classe abstraite. Par exemple, différents types d'employés ont des dispositions différentes, mais tous en reçoivent quelques-uns. Ainsi, la classe abstraite est appropriée pour la représenter car les points communs peuvent être exprimés dans une classe abstraite de base Employeeet la différence peut être implémentée dans des classes dérivées comme Managerou Workeretc.

Si vous souhaitez mettre l'accent uniquement sur le comportement polymorphe, choisissez l'interface. L'interface concerne davantage le contrat, c'est-à-dire un objet ou une hiérarchie disant qu'il est conforme à un certain comportement. Par exemple, tous les employés ont des dispositions de congé, mais différents types d'employés ont différents types de dispositions. Ainsi, chaque type différent d'employé nécessite une calculatrice de congés différente. Ici, l'interface est un bon choix car tous les types d'employés peuvent implémenter une LeaveCalculatorinterface avec un Calculate()comportement différent.

theD
la source
-3
  1. La principale différence est que les méthodes d'une interface Java sont implicitement abstraites et ne peuvent pas avoir d'implémentations. Une classe abstraite Java peut avoir des méthodes d'instance qui implémentent un comportement par défaut.
  2. Les variables déclarées dans une interface Java sont par défaut finales. Une classe abstraite peut contenir des variables non finales.
  3. Les membres d'une interface Java sont publics par défaut. Une classe abstraite Java peut avoir les saveurs habituelles des membres de la classe comme privée, protégée, etc.
  4. L'interface Java doit être implémentée à l'aide du mot clé «implements»; Une classe abstraite Java doit être étendue à l'aide du mot-clé "extend".
  5. Une interface peut étendre une autre interface Java, seule une classe abstraite peut étendre une autre classe Java et implémenter plusieurs interfaces Java.
  6. Une classe Java peut implémenter plusieurs interfaces mais elle ne peut étendre qu'une seule classe abstraite.
  7. L'interface est absolument abstraite et ne peut pas être instanciée; Une classe abstraite Java ne peut pas non plus être instanciée, mais peut être invoquée s'il existe un main ().
  8. Par rapport aux classes abstraites java, les interfaces java sont lentes car elles nécessitent une indirection supplémentaire.
  9. L'interface et la classe abstraite en Java sont que vous ne pouvez pas créer de méthode non abstraite dans l'interface, chaque méthode dans l'interface est par défaut abstraite, mais vous pouvez créer une méthode non abstraite dans la classe abstraite.
  10. La classe abstraite par rapport à l'interface en Java est que les interfaces sont mieux adaptées à la déclaration de type et la classe abstraite est plus adaptée à la réutilisation du code et à la perspective de l'évolution.
Sakina.A
la source