Invarianten und sichere Vererbung



Ähnliche Dokumente
Client-Server-Beziehungen

Verhindert, dass eine Methode überschrieben wird. public final int holekontostand() {...} public final class Girokonto extends Konto {...

SEP 114. Design by Contract

Objektorientierte Programmierung. Kapitel 12: Interfaces

Einführung in die Programmierung

Client-Server Beziehungen

Kapitel 6. Vererbung

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 22

Java: Vererbung. Teil 3: super()

Tagesprogramm

Nathan Burgener. Design by Contract. Modul SWE

Kapitel 6. Vererbung

Objektorientierte Programmierung

Prinzipien Objektorientierter Programmierung

Kapitel 6. Vererbung

Programmierkurs Java

Objektorientierte Programmierung

Lösungen zu Übung 3 Objektorientierte Modellierung - Statisches Modell

Kapitel 4. Mehrfachvererbung. Beispiel 1: typische Diamant Struktur. Person. Hiwi

Ersetzbarkeit, Client-Server Beziehungen

Software Engineering Klassendiagramme Assoziationen

Typumwandlungen bei Referenztypen

5. Abstrakte Klassen. Beispiel (3) Abstrakte Klasse. Beispiel (2) Angenommen, wir wollen die folgende Klassenhierarchie implementieren:

Sichtbarkeit & statische Methoden. Einsatz von Sichtbarkeit Einsatz statischer Methoden programmatische Realisierung 2 Beispielaufgaben

Java Einführung Abstrakte Klassen und Interfaces

Grundlagen der höheren Mathematik Einige Hinweise zum Lösen von Gleichungen

5. Abstrakte Klassen

Fachdidaktik der Informatik Jörg Depner, Kathrin Gaißer

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

geben. Die Wahrscheinlichkeit von 100% ist hier demnach nur der Gehen wir einmal davon aus, dass die von uns angenommenen

Folge 18 - Vererbung

Das Liskovsche Substitutionsprinzip

Klassenbeziehungen & Vererbung

Das Leitbild vom Verein WIR

Java Einführung Collections

Große Übung Praktische Informatik 1

Kapitel 9. Inner Classes. 9.1 Wiederholung: Iteratoren. Ausführen einer Operation auf allen Elementen einer Containerklasse

EinfÅhrung in die objektorientiere Programmierung (OOP) unter Delphi 6.0. EDV Kurs 13/2

VIII: Vererbung. Unterklassen einer Klasse. Vererbung von Methoden und Instanzvariablen. Überschreiben von Methoden

Java Kurs für Anfänger Einheit 5 Methoden

5.2 Neue Projekte erstellen

Grundlagen von Python

Programmieren in Java

Fachgebiet Informationssysteme Prof. Dr.-Ing. N. Fuhr. Programmierung Prof. Dr.-Ing. Nobert Fuhr. Übungsblatt Nr. 6

Vererbung & Schnittstellen in C#

Professionelle Seminare im Bereich MS-Office

Vererbung. Vererbung von Methoden und Instanzvariablen. Vererbung als Realisierung einer is-a Beziehung.

Wir gehen aus von euklidischen Anschauungsraum bzw. von der euklidischen Zeichenebene. Parallele Geraden schneiden einander nicht.

Aufgabenblatt Nr. 5 Generizität und TicTacToe

Java Einführung Umsetzung von Beziehungen zwischen Klassen. Kapitel 7

Informatik 2 Labor 2 Programmieren in MATLAB Georg Richter

Testen mit JUnit. Motivation

Die Bedeutung abstrakter Datentypen in der objektorientierten Programmierung. Klaus Kusche, September 2014

Dokumentation für die software für zahnärzte der procedia GmbH Onlinedokumentation

Prozentrechnung. Wir können nun eine Formel für die Berechnung des Prozentwertes aufstellen:

Scala kann auch faul sein

Klausur zur Einführung in die objektorientierte Programmierung mit Java

Hilfedatei der Oden$-Börse Stand Juni 2014

Eva Douma: Die Vorteile und Nachteile der Ökonomisierung in der Sozialen Arbeit

trivum Multiroom System Konfigurations- Anleitung Erstellen eines RS232 Protokolls am Bespiel eines Marantz SR7005

Einführung in die objektorientierte Programmierung mit Java. Klausur am 19. Oktober 2005

Factory Method (Virtual Constructor)

7 Rechnen mit Polynomen

OO Softwareentwicklung

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom b

13. Tutorium zu Programmieren

Leichte-Sprache-Bilder

ERGÄNZUNGEN ZUR ANALYSIS II MITTELWERTSATZ UND ANWENDUNGEN

Probeklausur Softwareengineering SS 15

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss

Whitebox-Vererbung vs. Blackbox-Vererbung. - Begriffsbestimmung - Vererbung öffentliche Vererbung private Vererbung - Zusammenfassung

Primzahlen und RSA-Verschlüsselung

1. Weniger Steuern zahlen

Institut für Programmierung und Reaktive Systeme 25. August Programmier-Labor Übungsblatt. int binarysearch(int[] a, int x),

Session Beans & Servlet Integration. Ralf Gitzel ralf_gitzel@hotmail.de

icloud nicht neu, aber doch irgendwie anders

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

Wichtig ist die Originalsatzung. Nur was in der Originalsatzung steht, gilt. Denn nur die Originalsatzung wurde vom Gericht geprüft.

Algorithmik II. a) Fügen Sie in einen anfangs leeren binären Baum die Schlüsselfolge 20, 28, 35, 31, 9, 4, 13, 17, 37, 25 ein.

SANDBOXIE konfigurieren

Klassendiagramm. Kurzer Überblick über UML - Stand BlaBla

Übungen zu Softwaretechnik

Übungen Programmieren 1 Felix Rohrer. Übungen

U08 Entwurfsmuster (II)

Fakultät Angewandte Informatik Lehrprofessur für Informatik

Papa - was ist American Dream?

.NET Code schützen. Projekt.NET. Version 1.0

Internet Explorer Version 6

Der lokale und verteilte Fall

Menü auf zwei Module verteilt (Joomla 3.4.0)

a n auf Konvergenz. Berechnen der ersten paar Folgenglieder liefert:

Das große ElterngeldPlus 1x1. Alles über das ElterngeldPlus. Wer kann ElterngeldPlus beantragen? ElterngeldPlus verstehen ein paar einleitende Fakten

Die Post hat eine Umfrage gemacht

Die Online-Meetings bei den Anonymen Alkoholikern. zum Thema. Online - Meetings. Eine neue Form der Selbsthilfe?

Windows XP Jugendschutz einrichten. Monika Pross Molberger PC-Kurse

Installation der SAS Foundation Software auf Windows

Schrittweise Anleitung zur Erstellung einer Angebotseite 1. In Ihrem Dashboard klicken Sie auf Neu anlegen, um eine neue Seite zu erstellen.

am Beispiel von JUnit

1. Man schreibe die folgenden Aussagen jeweils in einen normalen Satz um. Zum Beispiel kann man die Aussage:

Zeichen bei Zahlen entschlüsseln

Transkript:

Kapitel 7 Invarianten und sichere Vererbung Idee der Vererbung: class U extends O... bedeutet: Jedes U ist auch als O verwendbar, denn es hat mindestens dieselben Members im O-Subobjekt (Typkonformanz, IS-A ) Erweiterung des Typkonformanz-Begriffs auf Methodensignaturen führt zur sog. Kontravarianz (s.d.) Jedoch: U kann eine O-Methode so umdefinieren, dass sie etwas völlig anderes macht und nicht mehr zu den anderen O-Methoden paßt stärkere Forderung: Subtyping. Klienten-Code funktioniert auch mit U statt O ( Klientencode-Wiederverwendung, Liskov s Substitutionsprinzip, Inclusion Polymorphism [Cardelli]) 67

7.1. SUBTYPING/VERHALTENSKONFORMANZ 7. Invarianten und sichere Vererbung 7.1 Subtyping/Verhaltenskonformanz für Klienten sichere Vererbung erfordert Verhaltenskonformanz: 1. für jede Klasse wird eine Invariante formuliert (Prädikat über den Instanzvariablen), die vor und nach jedem Methodenaufruf gelten muß: {Inv(C) o.m(x) {Inv(C) 2. Die U-Invariante muß die O-Invariante implizieren (i.e. stärker sein): Inv(U) Inv(O) Beispiel: class Person{ String name; int alter; // Inv(Person) == 0 <= alter <= 150 class Student extends Person { int MatrNr; // Inv(Student) == (0 <= alter <= 30) // AND... MatrNr... 3. Für jede Methode m in O gilt: Pr e(o.m) Pr e(u.m) Post(U.m) Post(O.m) Die Oberklasse verlangt mehr (hat stärkere Preconditions- /kleineren Definitionsbereich der Methoden), die Unterklasse leistet mehr (hat stärkere Postconditions) 68

7.1. SUBTYPING/VERHALTENSKONFORMANZ 7. Invarianten und sichere Vererbung Dies sind strenge Forderungen, die aber absolute Sicherheit für den Klienten garantieren: auch aus Sicht des Methodenverhaltens ist jedes U-Objekt auch ein O-Objekt; Klientencode kann also garantiert unverändert bleiben wenn O durch U ersetzt wird Verhaltenskonformanz: U verlangt vom Klientencode weniger, aber bietet ihm mehr als O Dies kann nur funktionieren, wenn in die Implementierung von U erhöhter Aufwand geht Hauptanwendung: Unterklasse implementiert (abstrakte) Oberklasse Beispiel: Interface Set mit insert, lookup... Implementierung SortedList, die zusätzlich get/size hat Inv(Set) tr ue Inv(Sor tedlist) i 0..size() 2 : get(i) get(i + 1) P r e(set.inser t(x)) tr ue P r e(sor tedlist.inser t(x)) tr ue P ost(set.inser t(x)) lookup(x) = tr ue P ost(sor tedlist.inser t(x)) lookup(x) = tr ue In diesem einfachen Fall von Verhaltenskonformanz sind Pre/- Postkonditionen gleich, aber die Invarianten verschieden. Bsp. mit Klassen s.u. 69

7.2. INHERITANCE/SPEZIALISIERUNG 7. Invarianten und sichere Vererbung 7.2 Inheritance/Spezialisierung In der Praxis ist Konformanz eher selten. Häufiger ist Spezialisierung: Pr e(u.m) Pr e(o.m) Post(O.m) Post(U.m) U verlangt vom Klientencode mehr, aber bietet ihm (funktional) weniger Hauptanwendung: Postconditions gleich, U bietet spezielle (zb effizientere) Implementierung, die aber nicht für alle O- Fälle funktioniert Beispiel: Stack mit push, pop, top, isempty; Unterklasse BoundedStack mit zusätzlicher Methode isfull P r e(stack s.push(x)) true P r e(boundedstack s.push(x)) NOT s.isfull() Post(s.push(x)) s.top() = x Es gilt P r e(boundedstack s.push(x)) P r e(stack s.push(x)) Gelegentlich gibt es noch (Verhaltens-)Kovarianz: Pr e(o.m) Pr e(u.m) Post(O.m) Post(U.m) und (Verhaltens-)Kontravarianz: Pr e(u.m) Pr e(o.m) Post(U.m) Post(O.m) 70

7.3. BEISPIEL 7. Invarianten und sichere Vererbung 7.3 Beispiel Eine Klasse Bank erlaubt das Geld-Abheben von einem Konto mittels einer Methode abheben. Sie bietet einen Dispo-Kredit an, der als negativer Wert dargestellt wird - der Betrag, um den das Konto überzogen werden darf. class Bank { int konto; int dispo; public Bank(int k, int d) { konto = k; dispo = d; public void abheben(int betrag, Date datum) { konto -= betrag;... Die Vorbedingung für abheben ist P r e(bank b.abheben(int betrag, Date datum)) (konto betrag) dispo dispo 0 die Nachbedingung ist P ost(bank b.abheben(int betrag, Date datum)) (konto = konto betrag) 71

7.3. BEISPIEL 7. Invarianten und sichere Vererbung Eine Subklasse von Bank ist WeihnachtBank, die im Dezember den Dispokredit um 1000 Euro erhöht. Die Vorbedingung ist hier P r e(weihnachtbank k.abheben(int betrag,date datum)) (datum.month() = Dezember) (konto betrag (dispo 1000) dispo 0 (datum.month() Dezember) (konto betrag dispo dispo 0 die Nachbedingung ist P ost(weihnachtbank k.abheben(int betrag,date datum)) (konto = konto betrag) class WeihnachtBank extends Bank { public WeihnachtBank(int k, int d) { konto = k; dispo = d; public void abheben(int betrag, Date datum) { konto -= betrag;... WeihnachtBank erfüllt die Verhaltenskonformanz: wenn Vorbedingung für abheben der Klasse Bank gilt, dann auch für abheben von WeihnachtBank (Übung: nachrechnen!) wenn Nachbedingung von abheben in WeihnachtBank gilt, dann auch für abheben in Bank 72

7.3. BEISPIEL 7. Invarianten und sichere Vererbung Eine andere Bank namens KeinDispoBank gewährt keinen Dispokredit. Die Vorbedingung ist hier P r e(keindispobank r.abheben(int betrag,date datum)) (konto betrag 0) die Nachbedingung ist P ost(keindispobank r.abheben(int betrag,date datum)) (konto = konto betrag) class KeinDispoBank extends Bank { public KeinDispoBank(int k) { konto = k; dispo = 0; public void abheben(int betrag, Date datum) { konto -= betrag;... Hier ist die Verhaltenskonformanz nicht erfüllt: Vorbedingung für abheben von KeinDispoBank folgt nicht aus Vorbedingung für abheben von Bank KeinDispoBank ist also eine Spezialisierung von Bank. 73

7.4. QUADRAT/RECHTECK 7. Invarianten und sichere Vererbung Objekte von KeinDispoBank können daher nicht ohne weiteres als Objekte von Bank verwendet werden: class Client { void abheben (Bank bank, int betrag, Date datum) { bank.abheben(1000, datum); void main() { Bank b = new Bank(100, 1000); Bank w = new WeihnachtBank(100, 1000); Bank k = new KeinDispoBank(100); // Diese beiden Aufrufe werden // problemlos bearbeitet. abheben(b, 1000, 24.12.06); // konto = -1000 abheben(w, 1000, 24.12.06); // konto = -1000 // Nach diesem Aufruf hat der Benutzer // sein Konto ueberzogen! abheben(k, 1000, 24.12.06) // konto = -1000 7.4 Quadrat/Rechteck Bekanntes Beispiel: Klassen Rechteck und Quadrat mit x, y, setx(x), sety(y), area() In der Mathematik gilt: Ein Quadrat ist ein Rechteck (IS-A). Also Square extends Rectangle Ist das verhaltenskonformant? 74

7.4. QUADRAT/RECHTECK 7. Invarianten und sichere Vererbung Inv(Rectangle) true, Inv(Square) (x = y). Es gilt Inv(Square) Inv(Rectangle) Jedoch Pr e(r.setx(x)) true, Pr e(q.setx(x)) (x = Q. gety()), und erforderliche Implikation für Preconditions gilt nicht. Nimmt man für Unterklasse als setx-precondition auch true (weil man sonst gar nicht Seitenlänge ändern kann), kann Invariante Q.x = Q.y zerstört werden und damit auch Verhaltenskonformanz. Die Alternative Rectangle extends Square ist nicht vermittelbar, da gegen 2500 Jahre mathematische Tradition, und außerdem auch nicht verhaltenskonformant, da die erforderliche Implikation der Invarianten nicht gilt: Fügt man in Rectangle y neu hinzu und erbt x aus Square, dann ist für die Flächenberechnung wiederum die Verhaltenskonformanz zerstört, da P ost(r.area()) P ost(q.area ()) nicht gilt, denn Q.area() = Q.x 2, R.area() = R.x R.y, und R.x = R.y muss nicht gelten Also wie nun? gar keine Vererbungsbeziehung ist auch nicht vermittelbar. Vorschlag des Dozenten: Square extends Rectangle sowie zusätzliche Exceptions, falls Preconditions verletzt sind ( Programming by Contract, s.u.) Übung: Ist Complex Unterklasse von Real oder umgekehrt? Diskutieren Sie Verhaltenskonformanz! 75

7.5. INHERITANCE IS NOT SUBTYPING 7. Invarianten und sichere Vererbung 7.5 Inheritance is not Subtyping Man unterscheidet: Vererbung = Konformanz? Inheritance (Implementierung-Vererbung): Wiederverwendung von Methodenimplementierungen führt typischerweise zu Spezialisierung Subtyping (Subtyp-Vererbung): Wiederverwendung von Klienten-Code! jeder Code, der mit O-Objekten arbeitet, kann auch mit U-Objekten arbeiten führt zu Verhaltenskonformanz Durch Inheritance ist die Klassenimplementierung billiger, aber es entstehen Folgekosten beim Klienten (Absturz,...) durch Subtyping ist der Klientencode billiger (Lokalitätsprinzip für neue Unterklassen ist voll gewahrt), aber Unterklasse teurer (U.m() verlangt weniger, aber leistet mehr!) Wiederverwendung ist nie umsonst... eigentlich Trennung von Klassen und Typen notwendig; aber in Java, Eiffel,... nicht möglich. Jedoch: Java hat Trennung Interfaces/Klassen. Subtyping typischerweise durch Interface-Vererbung. In C++: private Inheritance: kein Subtyp! SATHER erlaubt explizite Trennung 76

7.6. VERERBUNG VS. DELEGATION 7. Invarianten und sichere Vererbung 7.6 Vererbung vs. Delegation Subtyping ist für den Klientencode sicher, Spezialisierung potentiell unsicher evtl. Ersetzung von Vererbung durch Delegation Delegation: Weiterreichen eines Aufrufs an referenziertes Objekt statt eigener Implementierung (Standardbeispiel: Adapter) Wir betrachten 3 Stack-Implementierungen: Stack mit verketteter Liste, BoundedStack mit statischem Array (nicht verhaltenskonformant, zusätzliche Methode isfull), SuperStack mit dynamischem Array (verhaltenskonformant) 1. Konformanter Fall: Delegation statt SuperStack extends Stack class Stack { Superstack s; public void push(object x) { s.push(x); Nachteil: zusätzlicher Aufruf, keine dynamische Bindung. Unsinnig. 77

7.6. VERERBUNG VS. DELEGATION 7. Invarianten und sichere Vererbung 2. Spezialisierungsfall: Delegation statt BoundedStack extends Stack class Stack { BoundedStack s; public void push(object x) { if (s.isfull()) throw new StackOverflow(); s.push(x); empfohlen von Radikalen, die Vererbung nur zulassen, wenn sie verhaltenskonformant ist Vorteil: zusätzliche Precondition wird geprüft Nachteil: keine volle Verhaltenskonformanz, keine dynamische Bindung Der Dozent bevorzugt deshalb Vererbung mit zusätzlicher Prüfung der Precondition: class BoundedStack extends Stack { int c = -1; int[] a = new int[42]; public void push(object x) { if (this.isfull()) { throw new StackOverflow(); c++; a[c] = x; public boolean isfull() {return c==41; 78

7.6. VERERBUNG VS. DELEGATION 7. Invarianten und sichere Vererbung 3. Amputationsfall: class Stack extends BoundedStack { public void isfull() { throw new IllegalStackOP(); entspricht P r e(stack.isfull(x)) = false; Postconditions sind gleich Amputation ist spezielle Spezialisierung! (Ansonsten ist Stack extends BoundedStack verhaltenskonformant, aber unsinnig...) 79