Liskov-Substitutionsprinzip

Das Liskov-Substitutionsprinzip (LSP) ist in der objektorientierten Programmierung eine besondere Definition des Begriffs Subtyp . Es wurde von Barbara Liskov und Jeannette Wing in einem Artikel mit dem Titel Family Values: A Behavioral Notion of Subtyping formuliert  :

Liskov und Wing schlugen die folgende kondensierte Formulierung vor:

Wenn es sich bei einem Objekt vom Typ um eine nachweisbare Eigenschaft handelt , gilt dies für jedes Objekt vom Typ , bei dem es sich um einen Subtyp von handelt .

Prinzip

Der von Liskov und Wing definierte Begriff des Subtyps basiert auf dem Begriff der Substituierbarkeit  : Wenn es sich um einen Subtyp von handelt , kann jedes Typobjekt durch ein Typobjekt ersetzt werden, ohne die gewünschten Eigenschaften des betreffenden Programms zu ändern.

Das Prinzip von Liskov beschränkt die Definition von Subtypen auf Signaturen:

Es werden auch eine Reihe von Verhaltensbedingungen definiert (siehe Abschnitt Design by Contract ).

Design nach Vertrag

Das Substitutionsprinzip von Liskov ist eng mit der Vertragsprogrammierungsmethode verbunden, was zu Einschränkungen führt, die festlegen, wie Verträge mit Vererbungsmechanismen interagieren können  :

Darüber hinaus impliziert das Substitutionsprinzip von Liskov, dass Ausnahmen eines neuen Typs nicht von Methoden der Unterklasse ausgelöst werden können, es sei denn, diese Ausnahmen sind selbst Untertypen der Ausnahmen, die von den Methoden der Oberklasse ausgelöst werden.

Eine Funktion, die Kenntnisse der Klassenhierarchie verwendet, verstößt gegen das Prinzip, da sie einen Verweis auf die Basisklasse verwendet, aber auch Kenntnisse über Unterklassen haben muss. Eine solche Funktion verstößt gegen das Open / Closed-Prinzip, da sie beim Erstellen einer von der Basisklasse abgeleiteten Klasse geändert werden muss.

Beispiel für eine LSP-Verletzung

Das klassische Beispiel für eine LSP-Verletzung ist:

Sie würden erwarten, eine Instanz des Typs Carréüberall dort verwenden zu können, wo ein Typ Rectangleerwartet wird.

Problem: Bei einem Quadrat mit per Definition vier gleichen Seiten ist es ratsam, die Änderung der Höhe und der Breite so einzuschränken, dass sie immer gleich sind. Wenn jedoch ein Quadrat verwendet wird, bei dem erwartet wird, dass es verhaltensmäßig mit einem Rechteck interagiert, kann es zu inkonsistenten Verhaltensweisen kommen: Die Seiten eines Quadrats können im Gegensatz zu denen eines Rechtecks ​​nicht unabhängig voneinander geändert werden. Eine schlechte Lösung wäre, den Setter des Quadrats zu modifizieren , um dessen Invarianz zu bewahren. Dies würde aber verletzt die Nachbedingung von dem Rechteck setter , der angibt , dass eine Höhe ändern kann und die Breite unabhängig.

Eine Lösung , um diese Inkonsistenzen zu vermeiden , ist die entfernen Mutable Natur der Carréund Klassen Rectangle. Mit anderen Worten, sie sind nur zum Lesen zugänglich. Es gibt keine Verletzung des LSP, jedoch muss man die Methoden "height" und "width" für ein Quadrat implementieren, was semantisch Unsinn ist.

Die Lösung besteht nicht darin, einen Typ Carréals Ersatz für einen Typ zu betrachten Rectangleund ihn als zwei völlig unabhängige Typen zu definieren. Dies widerspricht nicht der Tatsache, dass ein Quadrat ein Rechteck ist. Die Klasse Carréist ein Vertreter des Konzepts "Quadrat". Die Klasse Rectangleist ein Vertreter des Konzepts "Rechteck". Allerdings Vertreter teilen nicht die gleichen Eigenschaften wie das, was sie darstellen.

Erkennen einer LSP-Verletzung

Ein typischer Fall einer LSP-Verletzung kann leicht erkannt werden, wenn der Datentyperkennungsoperator verwendet wird, um das Verhalten entsprechend dem Objekttyp zu konditionieren. Zum Beispiel typeofin C oder C ++, isinstancein Python, instanceofin Java.

Zum Beispiel in der Python-Funktion:

def aFunction(anObject): if isinstance(anObject, AType): # do something elif isinstance(anObject, AnotherType): # do something else else: # default actions for the other case

Die Verwendung dieser Anweisung isinstancein einem Modul außerhalb der Klasse anObjectverstößt normalerweise gegen Liskovs Substitutionsprinzip und sollte durch die Ausnutzung des Polymorphismus in der Sprache ersetzt werden.

Anmerkungen und Referenzen

  1. Barbara Liskov , Wing, Jeannette , „  Familienwerte: Ein Verhaltensbegriff der Subtypisierung  “ ,16. Juli 1993(abgerufen am 5. Oktober 2006 ) .
  2. Barbara Liskov , Wing, Jeannette , „  Behavioral Subtyping Using Invariants and Constraints  “ ,Juli 1999(abgerufen am 5. Oktober 2006 ) .
  3. "  Episode 11, Das Liskov-Substitutionsprinzip - Teil 1  "

Zum Thema passende Artikel

<img src="https://fr.wikipedia.org/wiki/Special:CentralAutoLogin/start?type=1x1" alt="" title="" width="1" height="1" style="border: none; position: absolute;">