web-dev-qa-db-fra.com

Interfaces et héritage de classes abstraites, implémentation dans des classes étendues

Dans chaque exemple que j'ai vu, les classes étendues implémentent les interfaces de leurs parents. Pour référence, l'exemple suivant:

interface MyInterface{
    public function foo();
    public function bar();
}

abstract class MyAbstract implements MyInterface{
    public function foo(){ /* stuff */ }
    public function bar(){ /* stuff */ }
}

// what i usually see
class MyClass extends MyAbstract implements MyInterface{}

// what i'm curious about
class MyOtherClass extends MyAbstract{}

Ne pas implémenter une interface dans un enfant, qui est implémentée par un parent, est-il considéré comme une mauvaise pratique ou quelque chose du genre? Y a-t-il des inconvénients techniques à omettre la mise en œuvre chez l'enfant? 

34
Dan Lugg

Je considérerais que vous êtes sur le bon chemin. Il n'est pas nécessaire de déclarer que vous implémentez l'interface, lors de l'extension d'une classe qui la contient déjà implements. Pour moi, il ne s'agit que d'un autre code à conserver si des modifications sont nécessaires. Alors oui, vous avez raison!

20
Emil Ivanov

Le fait de ne pas implémenter une interface Chez un enfant, qui est implémentée par un parent , Est-il considéré comme une mauvaise pratique ou Quelque chose? Existe-t-il des inconvénients techniques À omettre la mise en œuvre de Chez l'enfant?

Je ne peux tout simplement pas répondre à votre question mieux que ce type a:

De par leur nature, même si parfois Elles peuvent sembler assez similaires, les classes abstraites Et les interfaces de classe servent des objectifs Très distincts. 

L'interface d'une classe est conçue comme un outil Pour "l'utilisateur" de cette classe. Une interface Est une présentation publique pour La classe, et elle devrait indiquer à Toute personne qui envisage de l’utiliser, quelles méthodes et constantes Sont disponibles et accessible de l'extérieur. Ainsi, Comme son nom l'indique, il se trouve toujours Entre l'utilisateur et la classe Qui l'implémente.

D'autre part, une classe abstraite Est un outil destiné à aider le "réalisateur" Des classes qui L'étendent. Il s’agit d’une infrastructure Qui peut imposer des restrictions et des Directives sur la forme que devraient prendre les classes Concrètes. Du point de vue de la conception de classe , Les classes abstraites Sont plus importantes sur le plan architectural Que les interfaces. Dans ce cas, le réalisateur Se situe entre la classe abstraite Et la classe concrète, en construisant Au-dessus de la première.

Référence

C'est donc à vous de décider en fonction de qui va utiliser (instancier) vos cours et qui va les écrire. Si vous êtes le seul utilisateur et rédacteur de vos cours, alors peut-être que vous n’avez peut-être pas besoin des deux. Toutefois, si vous souhaitez donner à chacun un plan détaillé pour les rédacteurs de classe et les utilisateurs de classe, vous devez envisager l’utilisation de l’abrégé et de la mise en œuvre.

18
Shef

Bien, j’étais confus aussi, mais je pense que vous devriez utiliser le dernier, vous avez raison, si vous implémentez l’interface dans la classe abstraite, il n’est pas nécessaire d’écrire l’interface, vous pouvez écrire la méthode dans interface tout en abstraite en tant que méthode abstraite, car vous allez étendre la classe abstraite de quelque manière que ce soit, et vous devrez utiliser la classe abstraite comme un type param lorsque vous utilisez la classe ailleurs, ce n'est pas une bonne chose, je pense qu'une classe abstraite ne devrait pas être utilisé en tant que type param, alors qu'une interface devrait l'être.

0
lvpiao

Ne pas implémenter une interface dans un enfant, qui est implémentée par un parent, est-il considéré comme une mauvaise pratique ou quelque chose du genre?

L'enfant implémente toujours l'interface, il ne peut pas y aller avec ça.

Je n'ai aucune idée si c'est une mauvaise pratique ou quelque chose. Je dirais que c'est une fonctionnalité linguistique.

Y a-t-il des inconvénients techniques à omettre la mise en œuvre chez l'enfant?

Vous ne pouvez pas tester le reflet de la classe abstraite pour avoir l'interface par exemple.

Cependant, les classes abstraites sont déjà une interface, donc techniquement, elles n'ont pas vraiment besoin de l'interface, mais vous pouvez le faire pour que les choses restent fluides au sein de l'héritage.

0
hakre

Peut-être un peu tard à la table, mais je vois que les commentaires ci-dessus ne clarifient pas le principal malentendu à la base de la question du PO.

Les questions sous-jacentes sont donc les suivantes:

  • Pourquoi utilisons-nous à la fois une classe abstraite et une interface sur la même ligne? 
  • Une méthode abstraite et une interface doivent-elles déclarer les mêmes méthodes?

Mais avant quelques précisions, pourquoi utiliser l’une ou l’autre des méthodes ci-dessus:

  • L'un ou l'autre est utilisé par un programmeur pour définir le contrat (exigences, obligations, limitations) que les autres programmeurs doivent respecter lorsqu'ils créent les classes concrètes (et éventuellement l'application logicielle complète) à partir des classes/interfaces abstraites développées par ce programmeur.
  • Une classe abstraite, à son tour, est utilisée pour fournir à la classe concrète créée plus tard le schéma directeur de méthodes et de structures de données via:

    1. déclarations de structures de données (facultatif),
    2. réalisations de base des méthodes (et leurs signatures, facultatif)
    3. juste des déclarations de méthodes (similaire à une utilisation d'interface, optionnel).
  • Une interface est utilisée pour fournir une classe concrète avec un plan de méthodes via

    1. juste les déclarations de méthodes (et leurs signatures, optionnelles).

Voici un exemple de résumé et de classes concrètes.

abstract class MyAbstractClass {

    public function foo() {
        // Base implementation of the method here.
    }

    public function bar() {
        // Base implementation of the method here.
    }

    // Effectively similar to baz() declaration within some interface:
    public abstract function baz($value);

}

class MyConcreteClass extends MyAbstractClass {

    // foo() and bar() are inherited here from MyAbstractClass.

    // baz() must be implemented or declared abstract again.
    public function baz($value) {
        // implementation.
    }

}

Alors les questions viennent:

  1. Pourquoi avons-nous besoin d'une interface ici? 
  2. Avons-nous besoin d'une interface pour dupliquer les mêmes déclarations de méthode?

Les réponses:

  1. Etant donné que PHP n'autorise qu'un seul héritage pour chaque sous-classe (vous ne pouvez pas écrire class MyConcreteClass extends MyAbstractClass, MyAnotherClass {}), lorsque nous devons étendre la fonctionnalité de classe concrète au-delà de la classe Abstract déjà utilisée, nous devons déclarer cette fonctionnalité supplémentaire via une seule. ou plusieurs interfaces.

    Comme ça:

    class MyConcreteClass 
        extends MyAbstractClass 
        implements MyInterface, MyAnotherInterface {
        // Methods and data implementations go here.
    }
    
  2. Comme résultat de la réponse 1, une interface préférable de ne pas le faire duplique une déclaration de méthodes d'une classe abstraite (ce qui est fondamentalement inutile). Une ou plusieurs interfaces doivent décrire les méthodes qui peuvent aider à améliorer la fonctionnalité concrète (ou une autre classe abstraite, pourquoi pas) pour permettre au programmeur de les utiliser avec le contrat ferme pour chaque objet construit au-dessus de ces classes et interfaces.

Enfin, répondre à la question du PO sur l’utilisation d’une interface pour une classe abstraite ou pour la classe concrète est:

  • à utiliser pour l'un ou les deux (ou au besoin) tant qu'une interface améliore un contrat de classe avec de nouvelles déclarations de méthodes.
0
bob-12345