Dein Thema

Prinzip der Liskov-Substitution, drittes SOLID-Prinzip

Untergeordnete Klassen sollten niemals Dateien beeinflussen oder ändern defiAnweisungen vom Typ der übergeordneten Klasse.

Das Konzept dieses Prinzips wurde 1987 von Barbara Liskov in einer Keynote der Konferenz vorgestellt und später 1994 zusammen mit Jannette Wing in einem Artikel veröffentlicht defiDie Originalversion lautet wie folgt:

Sei q (x) eine nachweisbare Eigenschaft für Objekte x vom Typ T. Dann sollte q (y) für Objekte y vom Typ S nachweisbar sein, wobei S ein Subtyp von T ist.

Anschließend wurde mit der Veröffentlichung der SOLID-Prinzipien von Robert C. Martin in seinem Buch „Agile Software Development, Principles, Patterns, and Practices“ und der anschließenden Neuveröffentlichung in der C#-Version des Buches „Agile Principles, Patterns, and Practices in C#“ das defiDieses Prinzip wurde als Liskov-Substitutionsprinzip bekannt.

Das bringt uns zum defiInformationen von Robert C. Martin: Subtypen müssen durch ihre Basistypen ersetzt werden können.

Einfacher gesagt, eine Unterklasse müsste die Methoden der übergeordneten Klasse so überschreiben, dass die Funktionalität aus Kundensicht nicht beeinträchtigt wird. Hier ist ein einfaches Beispiel, um das Konzept zu demonstrieren.

Klasse Fahrzeug {

    Funktion startEngine () {

        // Standard-Motorstartfunktion

    }

 

    Funktion beschleunigen () {

        // Standardbeschleunigungsfunktion

    }

}

Bei einer Fahrzeugklasse - sie kann abstrakt sein - und zwei Implementierungen:

Klasse Auto erweitert Fahrzeug {

    Funktion startEngine () {

        $ this-> engagIgnition ();

        parent :: startEngine ();

    }

 

    private function engagIgnition () {

        // Zündvorgang

    }

}

 

Klasse ElectricBus erweitert Fahrzeug {

    Funktion beschleunigen () {

        $ this-> erhöhungsspannung ();

        $ this-> connectIndividualEngines ();

    }

 

    private Funktion raiseVoltage () {

        // Elektrische Logik

    }

 

    private Funktion connectIndividualEngines () {

        // Verbindungslogik

    }

}

Klasse Fahrer {

    Funktion go (Fahrzeug $ v) {

        $ v-> startEngine ();

        $ v-> beschleunigen ();

    }

}

Eine Client-Klasse sollte beide verwenden können, wenn sie Vehicle verwenden kann.

Dies bringt uns zu einer einfachen Implementierung des Template Method Design Pattern, wie wir es im OCP verwendet haben.

Das zweite SOLID-Prinzip könnte Sie auch interessieren: https: //bloginnovazione.de / offen-geschlossen-zweites-prinzip-massiv / 3906 /

Aufgrund unserer bisherigen Erfahrungen mit dem Open / Closed-Prinzip können wir den Schluss ziehen, dass das Liskov-Substitutionsprinzip eng mit dem OCP verwandt ist. Tatsächlich ist "eine Verletzung von LSP eine latente Verletzung von OCP" (Robert C. Martin), und das Template Method Design Pattern ist ein klassisches Beispiel für den Respekt und die Implementierung von LSP, was wiederum eine der Lösungen ist, die ebenfalls eingehalten werden müssen mit OCP.

Beispiel für eine LSP-Verletzung

Klasse Rechteck {

    private $ topLeft;

    private $ width;

    private $ Höhe;

 

    öffentliche Funktion setHeight ($ height) {

        $ this-> height = $ height;

    }

 

Innovations-Newsletter
Verpassen Sie nicht die wichtigsten Neuigkeiten zum Thema Innovation. Melden Sie sich an, um sie per E-Mail zu erhalten.

    öffentliche Funktion getHeight () {

        return $ this-> height;

    }

 

    öffentliche Funktion setWidth ($ width) {

        $ this-> width = $ width;

    }

 

    öffentliche Funktion getWidth () {

        return $ this-> width;

    }

}

Beginnen wir mit einer geometrischen Grundform, einem Rechteck. Es ist nur ein einfaches Datenobjekt mit Setzern und Gettern für Breite und Höhe. Stellen Sie sich vor, unsere Anwendung funktioniert und wird bereits auf mehreren Clients bereitgestellt. Jetzt brauchen sie eine neue Funktion. Sie müssen in der Lage sein, Quadrate zu manipulieren.

Im wirklichen Leben, in der Geometrie, ist ein Quadrat eine bestimmte Form eines Rechtecks. Wir könnten also versuchen, eine Square-Klasse zu implementieren, die eine Rectangle-Klasse erweitert. Es wird oft gesagt, dass eine untergeordnete Klasse eine übergeordnete Klasse ist, und dieser Ausdruck entspricht zumindest auf den ersten Blick auch LSP.

Klasse Square erweitert Rechteck {

    öffentliche Funktion setHeight ($ value) {

        $ this-> width = $ value;

        $ this-> height = $ value;

    }

 

    öffentliche Funktion setWidth ($ value) {

        $ this-> width = $ value;

        $ this-> height = $ value;

    }

}

Ein Quadrat ist ein Rechteck mit gleicher Breite und Höhe, und wir könnten eine seltsame Implementierung wie im vorherigen Beispiel durchführen. Wir könnten beide Setter überschreiben, um sowohl Höhe als auch Breite einzustellen. Aber wie wirkt sich das auf den Client-Code aus?

Klasse Client {

    FunktionsbereichVerifier (Rechteck $ r) {

        $ r-> setWidth (5);

        $ r-> setHeight (4);

        if ($ r-> area ()! = 20) {

            neue Ausnahme werfen ('Schlechter Bereich!');

        }

        return true;

    }

}

Es ist denkbar, eine Client-Klasse zu haben, die den Bereich des Rechtecks ​​überprüft und eine Ausnahme auslöst, wenn dies falsch ist.

Funktionsbereich () {

    return $ this-> width * $ this-> height;

}

Wir haben offensichtlich die obige Methode zu unserer Rechteckklasse hinzugefügt, um den Bereich bereitzustellen.

Klasse LspTest erweitert PHPUnit_Framework_TestCase {

    Funktion testRectangleArea () {

        $ r = neues Rechteck ();

        $ c = neuer Client ();

        $ this-> assertTrue ($ c-> areaVerifier ($ r));

    }

}

Und wir haben einen einfachen Test erstellt, indem wir ein leeres rechteckiges Objekt an den Flächenprüfer gesendet haben und der Test bestanden wurde. Wenn unsere Klasse Quadrat ist defiWenn es korrekt abgeschlossen ist, sollte das Senden an den AreaVerifier() des Clients seine Funktionalität nicht beeinträchtigen. Schließlich ist ein Quadrat im mathematischen Sinne ein Rechteck. Aber ist es unsere Klasse?

Funktion testSquareArea () {

    $ r = neues Quadrat ();

    $ c = neuer Client ();

    $ this-> assertTrue ($ c-> areaVerifier ($ r));

}

Unsere Square-Klasse ist also doch kein Rechteck. Es bricht die Gesetze der Geometrie. Es schlägt fehl und verstößt gegen das Liskov-Substitutionsprinzip.

Ercole Palmeri

Innovations-Newsletter
Verpassen Sie nicht die wichtigsten Neuigkeiten zum Thema Innovation. Melden Sie sich an, um sie per E-Mail zu erhalten.

Aktuelle Artikel

Veeam bietet den umfassendsten Support für Ransomware, vom Schutz bis zur Reaktion und Wiederherstellung

Coveware by Veeam wird weiterhin Dienstleistungen zur Reaktion auf Cyber-Erpressungsvorfälle anbieten. Coveware wird Forensik- und Sanierungsfunktionen anbieten …

23. April 2024

Grüne und digitale Revolution: Wie vorausschauende Wartung die Öl- und Gasindustrie verändert

Die vorausschauende Wartung revolutioniert den Öl- und Gassektor mit einem innovativen und proaktiven Ansatz für das Anlagenmanagement.…

22. April 2024

Die britische Kartellbehörde schlägt bei BigTech Alarm wegen GenAI

Die britische CMA hat eine Warnung zum Verhalten von Big Tech auf dem Markt für künstliche Intelligenz herausgegeben. Dort…

18. April 2024

Casa Green: Energierevolution für eine nachhaltige Zukunft in Italien

Das „Green Houses“-Dekret, das von der Europäischen Union zur Verbesserung der Energieeffizienz von Gebäuden erlassen wurde, hat seinen Gesetzgebungsprozess mit… abgeschlossen.

18. April 2024