75 votes

Est-ce que les constructeurs doivent respecter le principe de substitution de Liskov?

Je m'efforce généralement de m'assurer que mes instances d'objet respectent le principe de substitution de Liskov, mais je me demande toujours si les gens pensent que le LSP devrait également s'appliquer aux constructeurs ?

J'ai essayé de chercher sur Google mais je n'ai pas pu trouver d'opinions fortes dans un sens ou dans l'autre.

Je tiens à préciser que la plupart de mon codage se fait en Ruby, mais il m'arrive parfois que les constructeurs de mes sous-classes soient légèrement différents de ceux de la classe parente. Ils prennent le même ensemble d'arguments de base, et parfois des arguments supplémentaires. Parfois, cela se produit également avec d'autres méthodes de classe.

Au fond de ma tête, cela m'a toujours semblé être une violation du LSP, mais je voulais savoir si quelqu'un d'autre ressentait la même chose.

5 votes

Je ne comprends pas pourquoi cela est fermé en tant que basé sur l'opinion. LSP est clairement indiqué et ne laisse aucune place à l'interprétation.

0 votes

D'accord, cela ne devrait pas avoir été fermé. Cette question concerne la théorie de l'informatique.

82voto

Philip JF Points 17248

Non, lorsque vous utilisez un constructeur, vous savez que vous traitez avec le sous-type. Cela vous permet d'avoir des préconditions non requises pour le constructeur parent telles que d'autres paramètres. C'est pourquoi dans la plupart des langues, le nom du constructeur est celui de la classe en cours de création.

Un bon exemple de cela est qu'un ColoredSquare pourrait être un sous-type approprié de Square, mais nécessite un paramètre supplémentaire : color. Si vous ne pouviez pas faire des choses comme ça, les sous-types seraient beaucoup moins utiles.

En quelque sorte, le constructeur n'est pas vraiment une partie du type : c'est une fonction qui renvoie un élément de ce type. Ainsi, définir un nouveau constructeur pour un sous-type ne casse pas le LSP.

10 votes

"quand vous utilisez un constructeur, vous savez que vous traitez avec le sous-type." Merci. C'est un excellent point.

0 votes

Il est probablement important de faire une distinction entre les constructeurs, les méthodes de fabrique statiques, les méthodes de fabrique qui sont des instances du type produit (notamment Clone), et les autres fabriques. Les fabriques statiques peuvent produire différents types d'objets dérivés du type de retour, mais le LSP devrait s'appliquer à tous les objets produits ; cependant, il n'est pas nécessaire que les classes dérivées supportent les mêmes méthodes statiques que la classe de base. Si une classe prend en charge une méthode de fabrique comme Clone, il convient de respecter le LSP et de prendre en charge des sémantiques similaires dans les sous-types.

0 votes

Pour les usines qui retournent des objets d'autres types, l'objet retourné par une usine dérivée devrait pouvoir être utilisé comme une instance d'un objet qui serait retourné par l'usine de base. Ainsi, si CarFactory a une méthode MakeCar() qui retourne Car, qui à son tour supporte une méthode Drive(), on devrait pouvoir appeler SomeCarFactory.MakeCar().Drive() même si SomeCarFactory est en réalité une FordFactory (qui hérite de CarFactory) qui retourne une Ford (qui hérite de Car).

16voto

kriss Points 10450

Definitely No.

Les constructeurs sont normalement spécialisés pour les sous-types. Essayer d'appliquer le LSP aux constructeurs reviendrait à dire que les sous-types ne peuvent pas avoir de méthodes ou de membres spécifiques ajoutés. Mais la restriction va seulement dans l'autre sens.

Et je suis également d'accord avec Philip, les constructeurs ne font pas vraiment partie d'un type (et dans certains langages, vous pouvez facilement utiliser d'autres fabriques à la place des constructeurs). En utilisant la terminologie Smalltalk, vous diriez que les constructeurs sont des méthodes des méta-classes.

Aucune violation du LSP ici, il s'applique uniquement aux méthodes d'instance, pas aux méthodes de classe (constructeurs ou autres méthodes de classe).

1voto

Jesus Ramos Points 15798

C'est une sorte de question subjective mais la façon dont j'ai tendance à écrire la mienne est telle que les paramètres supplémentaires n'ont pas vraiment d'incidence sur le changement de fonctionnalité. Cela signifie que lorsque mon constructeur nécessite un paramètre supplémentaire dans une sous-classe, c'est pour maintenir la fonctionnalité standard (mais en faisant des choses différentes en sous-jacentes) de cette manière, disons que je crée ClassA = new ClassB(avec quelques arguments); alors la fonctionnalité est la même que je fasse cela ou ClassA = new ClassA(); et j'utilise généralement une sorte de méthode Factory pour les créer, ce qui les rend transparents dans leur fonctionnement. Encore une fois, c'est juste ma façon de faire les choses et ce n'est en aucun cas la seule façon correcte de les faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X