Tire carré, de rectangle d'une violation de Liskov Substitution de Principe?
Je suis nouveau à la conception et à l'apprentissage des principes de conception.
Il dit découlant carré, de rectangle, est un exemple classique de violation de Liskov du Principe de Substitution.
Si c'est le cas, ce devrait être la bonne conception?
Vous devez vous connecter pour publier un commentaire.
Je crois que le raisonnement est quelque chose comme ceci:
Disons que vous avez une méthode qui accepte un rectangle et ajuste sa largeur:
Il doit être parfaitement raisonnable, compte tenu de ce qu'un rectangle est, à supposer que ce test pass:
... parce que changer un rectangle de la largeur de ne pas affecter sa hauteur.
Cependant, disons que vous avez tiré un nouveau Carré de classe à partir de Rectangle. Par définition, un carré a la hauteur et la largeur de toujours égale. Essayons de nouveau le test de:
Que le test échoue, car la définition d'un carré de la largeur de 100 va aussi changer sa hauteur.
Ainsi, Liskov substitution de principe est violé par la dérivation Carré, de Rectangle.
L' "est-un" la règle du sens dans le "monde réel" (un carré est certainement une sorte de rectangle), mais pas toujours dans le monde de la conception de logiciels.
Modifier
Pour répondre à votre question, la conception correcte devrait probablement être qu'à la fois Rectangle et le Carré de dériver à partir d'une commune "Polygone" ou "Forme" de la classe, qui est de ne pas appliquer les règles concernant la largeur ou la hauteur.
La réponse dépend de la mutabilité. Si votre rectangle et le carré de classes sont immuables, alors
Square
est vraiment un sous-type deRectangle
et il est parfaitement OK pour tirer d'abord à partir de la deuxième. Sinon,Rectangle
etSquare
pourrait à la fois exposer uneIRectangle
avec aucun des mutateurs, mais de dériver l'un de l'autre est faux, étant donné que ni le type est bien un sous-type de l'autre.IShape
plus de sens que laIRectangle
dans ce contexte. Qu'en pensez-vous?IShape
aurait du sens dans un contexte qui l'a examiné toutes les formes, y compris les non-rectangulaires, mais ce le contexte qui nous intéresse ici n'est pas. Nous parlons juste de carrés et de rectangles ici; les triangles et les cercles doivent pas s'appliquer.Je ne suis pas d'accord que dérivant carré, de rectangle nécessairement viole LSP.
Dans Matt exemple, si vous disposez d'un code qui s'appuie sur la largeur et la hauteur en étant indépendant, il n'en fait violer LSP.
Si toutefois, vous pouvez le remplacer par un rectangle, un carré partout dans votre code sans casser des hypothèses alors vous n'êtes pas violer LSP.
Si il vient vraiment à ce que l'abstraction rectangle moyens votre solution.
J'ai été aux prises avec ce problème beaucoup ces derniers temps et j'ai pensé ajouter mon chapeau dans l'anneau:
Avis le dernier de la classe,
ResizableRectangle
. En déplaçant le "resizableness" dans une sous-classe, nous obtenons le code de la réutilisation alors qu'en réalité l'amélioration de notre modèle. Pensez-y comme ça: un carré ne peut pas être librement redimensionnées, tout en restant un carré, alors que les carrés, les rectangles peuvent. Pas tous les rectangles peuvent être redimensionnées que, depuis un carré est un rectangle (et il ne peut pas être librement redimensionnées tout en conservant son "identité"). (o_O) il est Donc logique de faire une baseRectangle
classe qui n'est pas redimensionnable, puisque c'est un extra propriété de certains rectangles.Square
qui ne sont pas d'équerre en avoir un autre de la largeur et de la hauteur.Supposons que nous avons la classe Rectangle avec les deux (pour des raisons de simplicité public), les propriétés (largeur,hauteur. Nous pouvons modifier ces deux propriétés: r.largeur=1, r.hauteur=2.
Maintenant, nous dire un Carré is_a Rectangle. Mais si la demande est "un carré va se comporter comme un rectangle," on ne peut pas définir .largeur=1 et .hauteur=2 sur un objet carré (votre classe probablement ajuste la largeur si vous définissez la hauteur et vice versa). Il y a donc au moins un cas où un objet de type Carré ne se comporte pas comme un Rectangle, et, par conséquent, vous ne peut pas se substituer à eux (complètement).
Je crois que OOD/POO techniques existent pour permettre de logiciels pour représenter le monde réel. Dans le monde réel, un carré est un rectangle qui a des côtés égaux. Le carré est un carré seulement parce qu'il a des côtés égaux, non pas parce qu'il a décidé d'être un carré. Par conséquent, l'OO programme doit traiter avec elle. Bien sûr, si la routine de l'instanciation de l'objet veut qu'il soit carré, il peut spécifier la longueur de la propriété et de la propriété de largeur égale à la même quantité. Si le programme à l'aide de l'objet a besoin de savoir plus tard si il est carré, il suffit de lui demander. L'objet pourrait avoir une lecture seule propriété Booléenne appelée “Carré”. Lors de l'appel de la routine l'invoque, l'objet peut-retour (Longueur = Largeur). Maintenant, cela peut être le cas même si l'objet rectangle est immuable. En outre, si le rectangle est en effet immuable, la valeur de la Place de la propriété peut être définie dans le constructeur et être fait avec elle. Alors, pourquoi est-ce un problème? Le LSP exige une sous-objets immuables à appliquer et à carré étant un sous-objet d'un rectangle est souvent utilisé comme un exemple de sa violation. Mais cela ne semble pas être la bonne conception parce que lors de l'utilisation de la routine d'appel de l'objet comme “objSquare”, doivent en connaître les détails intimes. Ne serait-il pas mieux s'il s'en foutait de savoir si le rectangle est carré ou pas? Et ce serait à cause du rectangle méthodes serait correct, peu importe. Est-il un meilleur exemple, lorsque le LSP est violé?
Encore une question: comment un objet immuable? Est-il une “Immuable” de la propriété qui peuvent être définies à l'instanciation?
J'ai trouvé la réponse et c'est ce que j'attendais. Depuis que je suis un VB .NET développeur, c'est ce que je suis intéressé. Mais les concepts sont les mêmes à travers les langues. Dans VB .NET vous créez immuable classes en faisant les propriétés en lecture seule et que vous utilisez le Nouveau constructeur pour permettre l'instanciation de routine pour spécifier les valeurs de propriété lorsque l'objet est créé. Vous pouvez également utiliser des constantes pour certaines propriétés, et ils seront toujours les mêmes. De création de l'objet est immuable.
Le problème est que ce qui est décrit n'est pas vraiment un "type", mais un cumulatif de propriété émergente.
Tout ce que vous avez est un quadrilatère et que les deux "carrure" et "rectangleness" sont juste émergente des artefacts provenant de propriétés des angles et des côtés.
La notion de "Place" (ou même rectangle) est une représentation abstraite d'une collection de propriétés de l'objet dans la relation aux autres et l'objet en question, pas le type de l'objet et de soi-même.
C'est là que la pensée de le problème dans le contexte d'un sans type de langue peut aider, car il n'est pas le type qui détermine si c'est "un carré" mais les propriétés de l'objet qui détermine si c'est un "carré".
Je suppose que si vous voulez prendre l'abstraction encore plus loin que vous n'auriez même pas dire que vous avez un quadrilatère, mais que vous avez un polygone ou même juste une forme.
Son assez simple 🙂 Le plus de "base" de la classe (de la première à la dérivation de la chaîne d') doit être la plus générale.
Par exemple de la forme -> Rectangle -> Carré.
Ici un carré est un cas particulier d'un rectangle (avec contrainte dimensions) et d'un Rectangle est un cas particulier d'une forme.
Dit d'une autre façon d'utiliser la "est un" test de. Un écuyer est un rectangle. Mais un rectange n'est pas toujours un carré.