Liskov Substituion Principle

Einführung

1987 wurde das Liskov Substituion Principle (LSP), oder zu deutsch Liskovsche Substitutionsprinzip, von Barbara Liskov vorgestellt. Es ist eine spezielle Regelung für Subtypisierung von Klassen und besagt:

Ein Programm, das Objekte einer Basisklasse verwendet muss auch mit davon abgeleiteten Klassen funktionieren ohne, dass das die Funktion eingeschränkt wird.

Ist-Eine-Beziehung

Wird eine neue Klasse von einer bestehenden Klasse abgeleitet, erbt die neue Klasse sämtliche Eigenschaften und Methoden. Neue Methoden und Eigenschaften werden dann zu den bestehenden hinzugefügt und können auf diese zugreifen. Hierbei spricht man meist von einer Ist-Eine-Beziehung. Beispielsweise wäre die Klasse Cat von der Basisklasse Animal abgeleitet. Die Beziehung würden dann „Eine Katze ist ein Tier“ lauten und damit die Ableitung begründen.

UML


LSP1

C#

    public class Animal
    {
        public void Eat()
        {
            Console.WriteLine("*is eating*");
        }
    }

    public class Cat : Animal
    {
        public void Meow()
        {
            Console.WriteLine("MEOW!");
        }

JAVA

public class Animal {		
	public void Eat() {
		System.out.println("*is eating*");
	}
}

public class Cat extends Animal {
	public void Meow() {
		System.out.println("MEOW!");
	}
}

Ist-Doch-Keine?

Bei einem Beispiel von Wikipedia wird jedoch schnell klar, dass die Ist-Eine-Beziehungs-Regel nicht immer zutrifft. Von der Basisklasse GraphicalObject wird die Klasse Elipse abgeleitet – Eine Ellipse ist ein Grafisches Objekt. Die Klasse Circle wird wiederrum von Elipse abgeleitet – Ein Kreis ist eine Ellipse. Dies trifft soweit zu, führt jedoch zu Problemen, wenn das Oval über Methoden verfügt, um es in der Länge und Breite anzupassen. Würde Kreis diese Methoden erben könnte es sich demnach nicht mehr um einen Kreis handeln (Kreise sind bekanntlich immer gleich breit und lang).

UML


LSP2

C#

    public class GraphicalObject
    {
        public int Height { get; set; }
        public int Width { get; set; }
    }

    public class Elipse : GraphicalObject
    {
        public void SetHeight(int height)
        {
            Height = height;           
        }

        public void SetWidth(int width)
        {
            Width = width;
        }
    }

    public class Circle : Elipse
    {

    }

JAVA

public class GraphicalObject {
	public int Width;
	public int Height;
}

public class Elipse extends GraphicalObject {
    public void SetHeight(int height)
    {
        Height = height;           
    }

    public void SetWidth(int width)
    {
        Width = width;
    }
}

public class Circle extends Elipse {

}

Liskov Subtitution Principle_52BB5162

Durch das LSP wird dieses Problem aufgedeckt – die Aussage „die Achsen können unabhängig voneinander skaliert werden“ trifft nur auf eine Ellipse zu, nicht jedoch auf einen Kreis. Als Unterklasse von Ellipse müsste dies jedoch auch auf Kreis zutreffen. Dem LSP folgend, darf also nicht abgeleitet werden. Würden jedoch keine Methoden zur Manipulation der Höhe und Bereite in Ellipse existieren könnte die Ableitung problemlos erfolgen.

Abschließend

Es bedarf also etwas Denkarbeit und vor allem Erfahrung um dieses Prinzip anzuwenden. Steigende Robustheit und Fehlertoleranz des Codes machen diesen Aufwand aber allemal Wert.

Leave a Reply

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>