23.12.2012 Aufrufe

obj2 - Informatik

obj2 - Informatik

obj2 - Informatik

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

Fortgeschrittene Aspekte<br />

objektorientierter Programmierung<br />

Prof. Dr. Arnd Poetzsch-Heffter — AG Softwaretechnik<br />

Wintersemester 02/03


Inhalt


1. Einleitung<br />

Inhalt<br />

2. Grundlagen objektorientierter Sprachen<br />

3. Techniken zum Prüfen objektorientierter Programme<br />

4. Spezifikation objektorientierter Programme<br />

5. Verifikation spezifizierter Eigenschaften<br />

6. Ausblicke<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

3


1. Einleitung


1.1 Überblick<br />

1. Einleitung<br />

1.2 Formale und notationelle Grundlagen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

5


1.1 Überblick 6<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

1.1 Überblick


1.1 Überblick 7<br />

Ausgangspunkt:<br />

• Kenntnis objektorientierter Programmierung (z.B. Java)<br />

Lernziele:<br />

• technische Vertiefung in:<br />

◦ Semantik<br />

◦ Typisierung<br />

⊲ bessere Parametrisierung<br />

⊲ Ausdruck weiterer Eigenschaften<br />

◦ Spezifikation von Programmeigenschaften<br />

◦ Prüfen und Verifikation<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 8<br />

• konzeptionelle Vertiefung in:<br />

◦ objektorientierter Programmierung<br />

◦ objektorientierter Modellierung<br />

• Werkzeugentwicklung in diesem Bereich<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 9<br />

Semantik<br />

Zwei zentrale Aspekte:<br />

• Spezifikation von Programmeigenschaften<br />

• Spezifikation der Programmiersprache<br />

Beispiel(Semantik für Programmeigenschaften):<br />

public class List {<br />

int length;<br />

ListElems le;<br />

//@ invariant length == le.leng();<br />

...<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 10<br />

Beispiel(Programmiersprachensemantik):<br />

class IntPair {<br />

private int a;<br />

private int b;<br />

IntPair( int ai, int bi ){ a = ai; b = bi; }<br />

int sum(){ return this.add(); }<br />

private int add(){ return a+b; }<br />

}<br />

class IntTriple extends IntPair {<br />

private int a;<br />

IntTriple( int ai,int bi,int ci ){ super(ai,bi); a = ci; }<br />

int sum(){ return this.add(); }<br />

private int add(){ return super.sum() + a; }<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 11<br />

public class PrivateTest {<br />

public static void main( String[] arg ) {<br />

IntPair ip = new IntPair(3,9);<br />

IntTriple it = new IntTriple(1,2,27);<br />

System.out.println( ""+ip.sum()+" "+it.sum() );<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 12<br />

Typisierung:<br />

Typisierung<br />

Beschreibung von einfachen Eigenschaften<br />

• im Rahmen der Programmiersprachen<br />

• mit automatischer Prüfung durch den Übersetzer<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 13<br />

Beispiel(Parametrischer Polymorphismus):<br />

class LinkedList {<br />

Entry header = new Entry(null, null, null);<br />

int size = 0;<br />

}<br />

LinkedList() { ... }<br />

ET getLast() { ... }<br />

ET removeLast() { ... }<br />

void addLast(ET e) { ... }<br />

int size() { return size; }<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 14<br />

class Entry {<br />

ET element;<br />

Entry next;<br />

Entry previous;<br />

}<br />

Entry(ET element, Entry next, Entry previous) {<br />

this.element = element;<br />

this.next = next;<br />

this.previous = previous;<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 15<br />

class Test {<br />

public static void main( String[] args ) {<br />

LinkedList ls = new LinkedList();<br />

ls.addLast("erstes Element");<br />

ls.addLast("letztes Element");<br />

ls.getLast().indexOf("Elem"); // liefert 8<br />

}<br />

LinkedList lo = new LinkedList();<br />

lo.addLast( new Object() );<br />

lo.addLast( new Object() );<br />

lo.getLast().indexOf("Elem"); // Programmierfehler,<br />

} // der vom Uebersetzer automatisch entdeckt wird<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 16<br />

Spezifikation von Programmeigenschaften<br />

Spezifikation:<br />

• Beschreibung aussagekräftiger Eigenschaften<br />

◦ von Programmteilen oder -Schnittstellen<br />

◦ mit zusätzlichen Sprachmitteln<br />

• Prüfung mit unterschiedlichen Techniken<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 17<br />

Beispiel(Methodenspezifikation):<br />

public class IntMathOps {<br />

/*@ public normal_behavior<br />

@ requires y >= 0<br />

@ modifiable \nothing<br />

@ ensures \result * \result


1.1 Überblick 18<br />

Prüfen und Verifikation<br />

Aufgabe:<br />

Nachweis, dass beschriebenen Eigenschaften von<br />

Implementierung erfüllt werden.<br />

Techniken:<br />

• vollautomatisch vs. halbautomatisch/interaktiv<br />

• vollständig vs. teilweise<br />

• statisch vs. dynamisch<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 19<br />

Beispiel(Korrektheit):<br />

Aufgabe:<br />

Beweise, dass folgende Implementierung der Methode isqrt<br />

obige Spezifikation erfüllt.<br />

public static int isqrt( int y ){<br />

int count = 0, sum = 1;<br />

while (sum


1.1 Überblick 20<br />

Formale Techniken auf der Entwurfsebene<br />

Exemplarisch betrachten wir UML-Klassendiagramme<br />

annotiert mit OCL-Bedingungen (Object-constraint<br />

language)<br />

Beispiel(Annotiertes Klassendiagramm):<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 21<br />

Statisches Modell mit Bedingungen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 22<br />

1. Einleitung<br />

◦ Überblick<br />

Aufbau, Inhalt, Literatur<br />

◦ formale und notationelle Grundlagen<br />

2. Grundlagen objektorientierter Sprachen<br />

◦ Spracheigenschaften<br />

◦ Semantik objektorientierter Sprachen<br />

◦ Eigenschaften objektorientierter Programme<br />

◦ Modularität und Kapselung<br />

3. Techniken zum Prüfen objektorientierter Programme<br />

◦ Einführung in die Bedeutung von Typsystemen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 23<br />

◦ Typinformation und ihre statische und dynamische Prüfung<br />

◦ Typsicherheit<br />

◦ parametrische Typsysteme<br />

◦ virtuelle Klassen<br />

◦ erweiterte Typsysteme<br />

4. Spezifikation objektorientierter Programme<br />

◦ Grundlagen, Abstraktion, Kapselung<br />

◦ Spezifikation funktionaler Eigenschaften<br />

◦ Konformität von Subklassen (behavioral subtyping)<br />

◦ Spezifikation von Umgebungseigenschaften<br />

◦ Klassen- und Modulinvarianten<br />

◦ Modularitätsproblematik<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 24<br />

◦ Verfeinerung von Spezifikation<br />

5. Verifikation spezifizierter Eigenschaften<br />

◦ erweitertes dynamisches Prüfen<br />

◦ erweitertes statisches Prüfen<br />

◦ Programmverifikation<br />

◦ Strategien zur interaktiven Verifikation<br />

◦ Generierung schwächster Vorbedingungen<br />

6. Ausblicke<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.1 Überblick 25<br />

Literatur:<br />

• kein Buch, das gesamten Stoff abdeckt<br />

• Bücher über Vorlesungsteile<br />

• wissenschaftliche Artikel<br />

• Sprachspezifikationen<br />

Literatur wird kapitel-/abschnittsweise angegeben.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 26<br />

1.2 Formale und notationelle Grundlagen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 27<br />

• Die Sprache der (sortierten) Prädikatenlogik :<br />

◦ Signaturen<br />

◦ Terme<br />

◦ Formeln<br />

• Algebraische Datentypen<br />

• Abschließende Bemerkungen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 28<br />

Die Sprache der Prädikatenlogik<br />

Definition(Signatur):<br />

Eine Signatur Σ = (S, F ) besteht aus<br />

• einer Menge S von Sorten (Namen für Datentypen)<br />

• einer Menge F von Funktionssymbolen (Namen für<br />

Funktionen)<br />

so dass jede f ∈ F eine Funktionalität<br />

f : s1 × . . . × sn → s hat mit s1, . . . , sn, s ∈ S (n ≥ 0)<br />

Nullstellige Funktionen werden Konstanten genannt.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 29<br />

Beispiel(Signatur):<br />

1. Signatur der ganzen Zahlen:<br />

S = {Integer}<br />

F = {0 : → Integer<br />

succ : Integer → Integer<br />

pred : Integer → Integer<br />

+ : Integer × Integer → Integer<br />

− : Integer × Integer → Integer<br />

. . .}<br />

ΣINTEGER = (S, F )<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 30<br />

2. Signatur für Keller mit Elementen aus der Sorte Elem<br />

S = {Elem, Stack}<br />

F = {emptyStack : → Stack<br />

push : Stack × Elem → Stack<br />

pop : Stack → Stack<br />

top : Stack → Elem}<br />

ΣSTACK = (S, F )<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 31<br />

Bemerkung:<br />

• Im Folgenden gehen wir davon aus, dass<br />

◦ jede Signatur die Sorte Bool enthält und<br />

◦ für jede Sorte S eine Gleichheitsfunktion<br />

=S: S × S → Bool<br />

existiert.<br />

• Sorten spielen auf Spezifikationsebene die gleiche Rolle wie<br />

Typen in der Programmierung. Die terminologische<br />

Unterscheidung erleichtert im Folgenden die Trennung<br />

zwischen<br />

◦ der Sprache, die beschrieben wird, und<br />

◦ der Sprache, die zur Beschreibung verwendet wird.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 32<br />

Definition(Terme):<br />

Jede Signatur Σ = (S, F ) und S-sortierte Menge VAR von<br />

(logischen) Variablen erzeugt eine Menge T (Σ, VAR) von<br />

Termen, die aus Funktionssymbolen aus F und Variablen aus<br />

VAR (entsprechend der Funktionalitäten der<br />

Funktionssymbole und der Sorten der Variablen) bestehen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 33<br />

Beispiel(Terme):<br />

• Sei VARSTACK = {e : Elem, s : Stack},<br />

push(s, e), pop(push(s, e)), top(pop(push(s, e))),<br />

top(push(emptyStack, e)) sind Terme aus<br />

T (ΣSTACK, VARSTACK)<br />

• succ(0), succ(0) + succ(succ(0)) ∈ T (ΣINT EGER, ∅)<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 34<br />

Definition(Formeln):<br />

Sei Σ = (S, F ) eine Signatur, VAR eine S-sortierte Menge<br />

logischer Variablen und sei die Menge der Σ–Terme der<br />

Sorte s, bezeichnet als T (Σ, VAR)s. Die Menge der<br />

Σ–Formeln F (Σ) ist die kleinste Menge, die die folgenden<br />

Eigenschaften erfüllt:<br />

• jeder Term der Sorte Bool ist in F (Σ);<br />

• wenn G, H ∈ F (Σ), dann sind<br />

¬G, (G ∧ H), (G ∨ H), (G ⇒ H) und (G ⇔ H) in F (Σ);<br />

• wenn Xs ∈ VARs und G ∈ F (Σ), dann<br />

(∀Xs : G), (∃Xs : G) ∈ F (Σ).<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 35<br />

Bemerkung:<br />

• Um Klammern zu vermeiden, benutzen wir die folgenden<br />

Präzedenzen (von starke zu schwache Bindung):<br />

¬, ∧, ∨, ⇒, ⇔, ∀, ∃.<br />

• Prädikatenlogik wird im Folgenden hauptsächlich als<br />

Spezifikationssprache verwendet.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 36<br />

Algebraische Datentypen<br />

Beispiel(algebraische Datentypen):<br />

Sei Elem eine bereits definierte Sorte.<br />

Dann definiert<br />

data type<br />

ElemList = emptyElemList ()<br />

| app( first:Elem, rest:ElemList )<br />

end<br />

die Signatur (S,F):<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 37<br />

S = {ElemList}<br />

F = {emptyElemList : → ElemList<br />

app : Elem × ElemList → ElemList<br />

first : ElemList → Elem<br />

rest : ElemList → ElemList<br />

isemptyElemList : ElemList → Bool<br />

isapp : ElemList → Bool},<br />

wobei die Sorten und Funktionen die übliche Bedeutung<br />

haben. emptyElemList und app heißen die<br />

Konstruktorfunktionen (Konstruktoren) von (S,F).<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 38<br />

Abkürzend läßt sich der Datentyp ElemList auch so<br />

definieren:<br />

data type<br />

ElemList = list of Elem<br />

end<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 39<br />

Definition(Syntax algebraischer Datentypen):<br />

Deklarationen algebraischer Datentypen haben die Form:<br />

data type<br />

+<br />

end<br />

wobei<br />

::= <br />

| <br />

::= "list of" <br />

::= <br />

( "|" )*<br />

::= <br />

"(" [ Komponentendekl ("," Komponentendekl)* ] ")"<br />

Komponentendekl ::= [ ":"] <br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 40<br />

Zur Semantik algebraischer Datentypen:<br />

• unterschiedliche Konstruktorterme repräsentieren<br />

unterschiedliche Werte<br />

• alle Werte der Sorten sind erzeugt<br />

• Beweisprinzip: Induktion über den Aufbau der Terme<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 41<br />

Bemerkung:<br />

• Algebraische Datentypdeklarationen finden sich in den<br />

meisten funktionalen Programmiersprachen und sehr vielen<br />

Spezifikationssprachen.<br />

• Wichtiges Anwendungsgebiet ist die Spezifikation der<br />

abstrakten Syntax von Programmiersprachen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


1.2 Formale und notationelle Grundlagen 42<br />

Abschließende Bemerkungen<br />

• Weitere Spezifikationstechniken werden im Zusammenhang<br />

mit ihrer Anwendung erläutert.<br />

• Rekursive Prädikatspezifikationen werden für operationelle<br />

Semantik und Typeigenschaften benötigt.<br />

• Ziel ist hier: eine klare Sprachebene, um Eigenschaften von<br />

Programmiersprachen und von Programmen ausdrücken zu<br />

können.<br />

• Ziel ist hier nicht: Formalisierung in allen Details.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2. Grundlagen<br />

objektorientierter Sprachen


2. Grundlagen objektorientierter Sprachen<br />

2.1 Konzepte objektorientierter Programmierung<br />

2.2 Semantik objektorientierter Sprachen<br />

2.3 Eigenschaften objektorientierter Programme<br />

2.4 Modularität und Kapselung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

44


2.1 Konzepte objektorientierter Programmierung 45<br />

2.1 Konzepte objektorientierter<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

Programmierung


2.1 Konzepte objektorientierter Programmierung 46<br />

2.1.1 Grundkonzepte :<br />

• Objektkonzept<br />

• Klassifikation und Subtyping<br />

2.1.2 Sprachliche Konzepte :<br />

• Beschreibung von Objekten<br />

• Vererbungskonzept<br />

• dynamische Methodenauswahl<br />

• Zusammenwirken der Konzepte<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 47<br />

2.1.3 Pragmatische Aspekte :<br />

• Vererbung versus Subtyping<br />

• Objektorientierte Sicht auf Prozeduren und Klassen<br />

Ziel:<br />

• Wiederholung auf abstrakterem Niveau<br />

• Zusammenhang von Konzepten und Sprachmitteln<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 48<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

2.1.1 Grundkonzepte


2.1 Konzepte objektorientierter Programmierung 49<br />

Objektkonzept<br />

,,The basic philosophy underlying object-oriented programming is to<br />

make the programs as far as possible reflect that part of the reality they<br />

are going to treat. It is then often easier to understand and to get an<br />

overview of what is described in programs. The reason is that human<br />

beings from the outset are used to and trained in the perception of what<br />

is going on in the real world. The closer it is possible to use this way of<br />

thinking in programming, the easier it is to write and understand<br />

programs.“<br />

aus: Object-oriented Programming in the BETA Programming Language<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 50<br />

Objektorientiertes Paradigma:<br />

Betrachte ein Softwaresystem als eine Menge kooperierender<br />

Objekte.<br />

a1:<br />

a2:<br />

obj1<br />

m(p1,p2) {..}<br />

m1() {..}<br />

m2( p ) {..}<br />

<strong>obj2</strong><br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

. m( 1814, "SS1999")<br />

a:<br />

<strong>obj2</strong><br />

m(p1,p2) {..}<br />

n( p,r ) {..}


2.1 Konzepte objektorientierter Programmierung 51<br />

Objekte sind eigenständige Ausführungseinheiten mit:<br />

• Zustand<br />

• Identität<br />

• Lebensdauer<br />

• Aufenthaltsort<br />

• Verhalten<br />

Im Vergleich zur prozeduralen Programmierung:<br />

• andere Programmstruktur<br />

• anderes Ausführungsmodell<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 52<br />

Konsequenz des Objektkonzepts:<br />

• saubere Schnittstellenbildung<br />

◦ öffentlich zugängliche Methoden<br />

◦ öffentlich zugängliche Attribute<br />

• Schnittstelle verbirgt Implementierung (Information<br />

Hiding)<br />

• Schnittstelle ist Basis für Verhaltensbeschreibung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 53<br />

Klassifikation:<br />

Klassifikation und Subtyping<br />

Klassifizieren ist eine allgemeine Technik, um Wissen über<br />

Begriffe, Dinge und deren Eigenschaften hierarchisch zu<br />

strukturieren. Das Ergebnis nennen wir eine Klassifikation.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 54<br />

Beispiel(Klassifikation der Rechtsgebiete):<br />

Öffentliches<br />

Recht<br />

Bürgerliches<br />

Recht<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

Recht<br />

Privatrecht Kirchenrecht<br />

Handelsrecht Urheberrecht


2.1 Konzepte objektorientierter Programmierung 55<br />

Beispiel(Klassifikation der Wirbeltiere):<br />

Wirbeltiere<br />

Fische Lurche Reptilien Säugetiere Vögel<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

Wale Primaten Paarhufer


2.1 Konzepte objektorientierter Programmierung 56<br />

Beispiel(Klassifikation der Figuren):<br />

Ellipse<br />

Kreis<br />

Figur<br />

Vieleck<br />

Viereck Dreieck<br />

Parallelogramm<br />

Raute Rechteck<br />

Quadrat<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

Der Pfeil ↗<br />

repräsentiert die<br />

ist-ein-Beziehung.<br />

Ziel: Anwendung der<br />

Klassifikationstechnik<br />

auf Software-Objekte


2.1 Konzepte objektorientierter Programmierung 57<br />

Beobachtungen zu Klassifikationen:<br />

• Sie können sich auf Objekte oder Gebiete beziehen.<br />

• Sie können baumartig oder DAG-artig sein.<br />

• Objektklassifikationen begründen ist-ein-Beziehungen.<br />

• abstrakte Klassen vs. nicht abstrakte Klassen<br />

Prinzip der Substitution:<br />

Überall, wo Oberklassenobjekte erwartet werden, lassen sich<br />

auch Unterklassenobjekte verwenden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 58<br />

In der Softwaretechnik:<br />

1. Klassifikation syntaktisch:<br />

Unterklassenobjekte haben größere Schnittstellen als<br />

Oberklassenobjekte (Auswirkung auf<br />

Programmiersprache).<br />

2. Klassifikation semantisch:<br />

Unterklassenobjekte bieten mindestens das Verhalten,<br />

welches Oberklassenobjekte haben.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 59<br />

Abstraktion:<br />

... das Heraussondern des unter einem bestimmten<br />

Gesichtspunkt Wesentlichen vom Unwesentlichen.<br />

[Meyers großes Taschenlexikon]<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 60<br />

Mittels Abstraktion:<br />

• ausgehend von unterschiedlichen Objekten oder Typen mit<br />

gemeinsamen Eigenschaften<br />

• Ausarbeitung eines abstrakteren Typs, der die<br />

gemeinsamen Eigenschaften zusammenfasst<br />

• entspricht dem Verkleinern der Schnittstelle<br />

• Programme, die sich nur auf diese gemeinsamen<br />

Eigenschaften stützen, arbeiten dann für alle Objekte des<br />

abstrakteren Typs.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 61<br />

Beispiel(Abstraktion):<br />

class Student {<br />

String name;<br />

int matNr;<br />

...<br />

void drucken() {<br />

System.out.<br />

println( name );<br />

System.out.<br />

println( matNr );<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

class Professor {<br />

String name;<br />

int telNr;<br />

...<br />

void drucken() {<br />

System.out.<br />

println( name );<br />

System.out.<br />

println( telNr );<br />

}<br />

}


2.1 Konzepte objektorientierter Programmierung 62<br />

Abstraktion:<br />

• Typ Person mit<br />

Methode drucken<br />

• Algorithmus auf<br />

Basis von Person<br />

Anwendungsbeispiele:<br />

• Ein/Ausgabe-Schnittstellen<br />

• Fenstersysteme<br />

• ...<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

Person[] p = new Person[4];<br />

p[0] = new Student(...);<br />

p[1] = new Professor(...);<br />

...<br />

for(i=1; i


2.1 Konzepte objektorientierter Programmierung 63<br />

interface Person {<br />

void drucken();<br />

}<br />

class Student implements Person {<br />

...<br />

}<br />

class Professor implements Person {<br />

...<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 64<br />

Spezialisierung:<br />

... das Hinzufügen speziellerer Eigenschaften zu einem<br />

Gegenstand oder das Verfeinern eines Begriffs durch<br />

Einführen weiterer Merkmale.<br />

(z.B. berufliche Spezialisierung)<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 65<br />

Mittels Spezialisierung:<br />

• ausgehend von allgemeinen Objekten bzw. Typen<br />

• Erweiterung dieser Objekte und ihrer Implementierung<br />

• entspricht dem Hinzufügen von zusätzlichen und<br />

spezielleren Eigenschaften<br />

• Voraussetzung: spezialisierte Objekte verhalten sich<br />

konform zu den allgemeineren Objekten<br />

• Programme, die auf den allgemeineren Objekten arbeiten,<br />

arbeiten dann auch korrekt auf den spezielleren Objekten.<br />

• Vererben von Implementierungsteilen,Wiederverwendung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 66<br />

Beispiel(Spezialisierung):<br />

Spezialisierung:<br />

• Entwickle<br />

Implementierung zu<br />

Typ Person.<br />

• Spezialisiere sie.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

class Person {<br />

String name;<br />

...<br />

void drucken(){<br />

System.out.println(name);<br />

}<br />

}


2.1 Konzepte objektorientierter Programmierung 67<br />

Vererbt werden:<br />

• Attribute<br />

• Methoden<br />

Methoden können in<br />

Subklassen<br />

überschrieben werden<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

class Student extends Person {<br />

int matNr;<br />

...<br />

void drucken(){<br />

super.drucken();<br />

System.out.println(matNr);<br />

}<br />

}<br />

class Professor extends Person {<br />

int telNr;<br />

...<br />

void drucken(){<br />

super.drucken();<br />

System.out.println(telNr);<br />

}<br />

}


2.1 Konzepte objektorientierter Programmierung 68<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

2.1.2 Sprachliche Konzepte


2.1 Konzepte objektorientierter Programmierung 69<br />

• Klassenkonzept<br />

• Prototypkonzept<br />

Beschreibung von Objekten<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 70<br />

Klassenkonzept:<br />

• Der Programmierer beschreibt nicht einzelne Objekte,<br />

sondern deklariert Klassen.<br />

• Klasse = Beschreibung der Eigenschaften, die die Objekte<br />

dieser Klasse haben sollen<br />

• Während der Programmausführung werden Objekte zu<br />

deklarierten Klassen erzeugt (Instanzieren).<br />

• Klassen können zur Ausführungszeit nicht verändert werden.<br />

• Klassendeklaration entspricht der Deklaration von<br />

Verbundtypen imperativer Sprachen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 71<br />

Prototypkonzept:<br />

• Der Programmierer beschreibt direkt einzelne Objekte.<br />

• Neue Objekte werden durch Klonen existierender Objekte<br />

und Verändern ihrer Eigenschaften zur Ausführungszeit<br />

erzeugt.<br />

• Klonen eines Objekts obj = Erzeugen eines neuen Objekts,<br />

das die gleichen Eigenschaften wie obj besitzt.<br />

• Verändern = dem Objekt werden weitere Attribute<br />

hinzugefügt oder Methoden werden durch andere ersetzt.<br />

• Umgesetzt beispielsweise in der Sprache Self.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 72<br />

Vererbung:<br />

Vererbungskonzept<br />

Sprachlich unterstützte Wiederverwendungsmöglichkeit der<br />

Eigenschaften/des Codes einer anderen Klasse:<br />

• meist mit Subtyping gekoppelt<br />

• ergänzt um Spezialisierungsmöglichkeiten:<br />

◦ Hinzufügen von Attributen, Methoden, etc.<br />

◦ Überschreiben von Methoden<br />

◦ Verwenden überschriebener Methoden<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 73<br />

Ziele:<br />

• fehlerträchtiges Kopieren von Code vermeiden<br />

• Reduktion der Programmgröße<br />

• Spezialisierung von Schnittstellen, bei denen Kopieren<br />

bzw. Modifizieren nicht möglich ist<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 74<br />

Beispiel(Vererbung):<br />

class Person {<br />

String name;<br />

int geburtsdatum; /* in der Form JJJJMMTT */<br />

void drucken() {<br />

System.out.println("Name: "+ this.name);<br />

System.out.println("Geburtsdatum: "+ geburtsdatum);<br />

}<br />

boolean hat_geburtstag ( int datum ) {<br />

return (geburtsdatum % 10000) == (datum % 10000);<br />

}<br />

Person( String n, int gd ) {<br />

name = n;<br />

geburtsdatum = gd;<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 75<br />

class Student extends Person {<br />

int matNr;<br />

int semester;<br />

void drucken() {<br />

super.drucken();<br />

System.out.println( "Matrikelnr: " + matNr );<br />

System.out.println( "Semesterzahl: " + semester );<br />

}<br />

Student( String n, int gd, int mnr, int sem ) {<br />

super( n, gd );<br />

matNr = mnr;<br />

semester = sem;<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 76<br />

Dynamische Methodenauswahl<br />

Methodenauswahl:<br />

• statisch:<br />

Zur Übersetzungszeit wird jeder Aufrufstelle die<br />

auszuführende Methode zugeordnet.<br />

• dynamisch:<br />

Zur Laufzeit wird an der Aufrufstelle das Zielobjekt<br />

berechnet und in Abhängigkeit vom Zielobjekt die<br />

auszuführende Methode ausgewählt.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 77<br />

Bemerkung:<br />

Dynamische Methodenauswahl ist Voraussetzung:<br />

• für Spezialisierung<br />

• für das Arbeiten mit abstrakten Klassen und Schnittstellen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 78<br />

Zusammenwirken der Konzepte<br />

Beispiel(Abstract Window Toolkit):<br />

1. Die Elemente der Bedienoberfläche werden als Objekte<br />

modelliert.<br />

2. Oberflächenelemente werden klassifiziert:<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 79<br />

Canvas<br />

Label<br />

Button<br />

List<br />

Choice<br />

CheckBox<br />

Scrollbar<br />

Object<br />

Component<br />

TextComponent<br />

TextArea TextField<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

Container<br />

ScrollPane Window Panel<br />

Frame<br />

Dialog<br />

FileDialog<br />

Applet


2.1 Konzepte objektorientierter Programmierung 80<br />

3. Gemeinsame Programmteile werden in der abstrakten<br />

Klasse Component zusammengefasst und von dort vererbt<br />

(über 100 Methoden).<br />

4. Viele Klassen benutzen die Klasse Component als<br />

Abstraktion.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 81<br />

Beispiel(Verwendung von Abstraktion):<br />

public class Container extends Component {<br />

...<br />

public Component getComponent(int n) { ... }<br />

public Component[] getComponents() { ... }<br />

public Component add(Component comp) { ... }<br />

public Component add(Component comp, int index) { ... }<br />

...<br />

public void remove(Component comp) { ... }<br />

...<br />

public Component getComponentAt(int x, int y) { ... }<br />

...<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 82<br />

5. Dynamische Methodenauswahl ist Vorausssetzung für das<br />

Funktionieren der Komponentenhierarchie und für die<br />

Anbindung der zu steuernden Anwendungen über die<br />

Listener-Schnittstellen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 83<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

2.1.3 Pragmatische Aspekte


2.1 Konzepte objektorientierter Programmierung 84<br />

Vererbung versus Subtyping<br />

1. Subtyping ohne Vererbung:<br />

Objektorientierte Programmierung kann auf Vererbung<br />

verzichten, aber nicht auf Subtyping und dynamische<br />

Methodenauswahl<br />

Beispiel(Delegation statt Vererbung):<br />

interface Person {<br />

String getName();<br />

int getGeburtsdatum();<br />

void drucken();<br />

boolean hat_geburtstag( int datum );<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 85<br />

public class PersonCl implements Person {<br />

String name;<br />

int geburtsdatum; /* in der Form JJJJMMTT */<br />

}<br />

public PersonCl( String n, int gd ) {<br />

name = n;<br />

geburtsdatum = gd;<br />

}<br />

public String getName() { return name; }<br />

public int getGeburtsdatum() { return geburtsdatum; }<br />

public void drucken() {<br />

System.out.println("Name: "+ this.name);<br />

System.out.println("Geburtsdatum: "+ this.geburtsdatum);<br />

}<br />

public boolean hat_geburtstag ( int datum ) {<br />

return (this.geburtsdatum%10000) == (datum%10000);<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 86<br />

interface Student extends Person {<br />

public int getMatNr();<br />

public int getSemester();<br />

}<br />

public class StudentCl implements Student {<br />

Person personPart;<br />

int matNr;<br />

int semester;<br />

StudentCl( String n, int gd, int mnr, int sem ) {<br />

personPart = new PersonCl( n, gd );<br />

matNr = mnr;<br />

semester = sem;<br />

}<br />

public String getName() { return personPart.getName(); }<br />

public int getGeburtsdatum() { return personPart.getGeburtsdatum(); }<br />

public void drucken() {<br />

personPart.drucken();<br />

System.out.println( "Matrikelnr: " + matNr );<br />

System.out.println( "Semesterzahl: " + semester );<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 87<br />

}<br />

public boolean hat_geburtstag( int datum ) {<br />

return personPart.hat_geburtstag( datum );<br />

}<br />

public int getMatNr() { return matNr; }<br />

public int getSemester() { return semester; }<br />

public class Test {<br />

public static void main( String[] argv ) {<br />

int i;<br />

Person[] pf = new Person[3];<br />

pf[0] = new PersonCl( "Meyer", 19631007 );<br />

pf[1] = new StudentCl( "Schmidt", 19641223, 6758475, 5 );<br />

pf[2] = new StudentCl( "Planck", 18580423, 3454545, 47 );<br />

}<br />

}<br />

for( i = 0; i


2.1 Konzepte objektorientierter Programmierung 88<br />

2. Vererbung ohne Subtyping:<br />

Vererbung wird teilweise zur Codewiederverwendung<br />

benutzt, ohne eine ist-ein-Beziehung zwischen Subklassenund<br />

Superklassenobjekt zu etablieren (problematisches<br />

Vorgehen).<br />

Beispiel(Vererbung ohne Subtyping):<br />

public class List {<br />

public boolean contains( int i ) { return true; }<br />

public int getFirst( ) { return 0;}<br />

public void addFirst( int i ) { }<br />

public void removeFirst() { }<br />

public void remove( int i ) { }<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 89<br />

public class Set extends List {<br />

public int getSome() { return getFirst(); }<br />

public void add( int i ) {<br />

addFirst(i);<br />

}<br />

public void addFirst( int i ) {<br />

if( !contains(i) ) super.addFirst(i);<br />

}<br />

public void removeFirst() {<br />

System.out.println("Should not be used!!");<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 90<br />

Objektorientierte Sicht auf Prozeduren und<br />

Klassen<br />

1. Zeiger auf Prozeduren lassen sich über Objekte realisieren:<br />

◦ definiere Schnittstellentyp mit einer Methode, deren Signatur der<br />

Prozedursignatur entspricht<br />

◦ für jede Prozedur p implementiere den Schnittstellentyp durch<br />

Klasse KP.<br />

◦ statt dem Zeiger auf die Prozedur p übergebe KP-Objekt op<br />

◦ Aufruf: op.p(...)<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 91<br />

Beispiel(Zeiger auf Prozeduren):<br />

Call-back-Prozeduren werden im AWT durch sogenannte<br />

Listener-Objekte realisiert, die eine Listener-Schnittstelle<br />

implementieren. Besitzt diese Schnittstelle genau eine<br />

Methode, ergibt sich ein Verhalten wie bei<br />

Prozedurzeigern.<br />

public interface ActionListener extends EventListener {<br />

/**<br />

* Invoked when an action occurs.<br />

*/<br />

public void actionPerformed(ActionEvent e);<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 92<br />

2. Analogie zwischen Prozeduren und Klassen:<br />

◦ beides sind statische Programmelemente, von denen zur Laufzeit<br />

Instanzen gebildet werden (Prozedurinkarnationen, Objekte)<br />

◦ Prozedurinkarnationen und Objekte besitzen Identität, Zustand und<br />

Lebensdauer.<br />

◦ Besitzt ein Objekt einen eigenen Thread und kann es sein Ende selbst<br />

bestimmen (aktives Objekt), verhält es sich wie eine<br />

Prozedurinkarnation, die während der Laufzeit von ”außen”<br />

angesprochen werden kann.<br />

BETA nutzt diese Analogie und vereinheitlicht Klassen und<br />

Methoden zu sogenannten Pattern.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 93<br />

3. Klassen als Objekte:<br />

Betrachtet man eine Klasse als Objekt, muss sie für ihre<br />

Aufgaben Methoden bereitstellen:<br />

◦ Erzeugen von Objekten<br />

◦ Auskunft über ihre Eigenschaften geben<br />

◦ Konstruktion neuer Klassen ermöglichen<br />

Beispiel(Introspektion in Java):<br />

import java.lang.reflect.*;<br />

public class Inspektor {<br />

public static void main(String[] ss) {<br />

try{<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.1 Konzepte objektorientierter Programmierung 94<br />

}<br />

}<br />

Class klasse = Class.forName( ss[0] );<br />

Method[] methoden = klasse.getMethods();<br />

for( int i = 0; i < methoden.length; i++ ){<br />

Method m = methoden[i];<br />

Class retType = m.getReturnType();<br />

String methName = m.getName();<br />

Class[] parTypes = m.getParameterTypes();<br />

System.out.print(retType.getName()+" "+methName+"(");<br />

for( int j = 0; j < parTypes.length; j++ ){<br />

if( j > 0 ) System.out.print(", ");<br />

System.out.print( parTypes[j].getName() );<br />

}<br />

System.out.println( ");" );<br />

}<br />

} catch( ClassNotFoundException e ) {<br />

System.out.println("Klasse "+ss[0]+" nicht gefunden");<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 95<br />

2.2 Semantik objektorientierter Sprachen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

2.2.1 Einführung


2.2 Semantik objektorientierter Sprachen 96<br />

Anwendungen von Semantikspezifikationen:<br />

• Sprachspezifikation<br />

• Hilfe beim Sprachentwurf<br />

• Grundlage zum Beweis von Spracheigenschaften<br />

• Grundlage zum Beweis von Programmeigenschaften<br />

• Klärung bei der Programmierung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 97<br />

Beispiel(Binden von Attributen):<br />

class A {<br />

int i=1;<br />

int m() { return i*100; }<br />

int n() { return i+m(); }<br />

}<br />

class B extends A {<br />

int i=10;<br />

int m() { return i*1000; }<br />

int p() { return n(); }<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 98<br />

public class Bindung {<br />

int m() {<br />

A[] ar = { new A(), new B() };<br />

return ar[0].i + ar[0].m() + ar[1].i + ar[1].m();<br />

}<br />

}<br />

public static void main(String[] argv) {<br />

A a = new B();<br />

System.out.println(new A().m()); /* 1 */<br />

System.out.println(a.m()); /* 2 */<br />

System.out.println(a.i); /* 3 */<br />

System.out.println(new B().p()); /* 4 */<br />

System.out.println(new Bindung().m()); /* 5 */<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 99<br />

Beispiel(Binden von super-Aufrufen):<br />

class C1 {<br />

void m(){<br />

System.out.println("in C1");<br />

}<br />

}<br />

class C2 extends C1 {<br />

void m(){<br />

System.out.println("in C2");<br />

super.m();<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 100<br />

class C3 extends C2 { }<br />

class C4 extends C3 {<br />

void m(){<br />

System.out.println("in C4");<br />

super.m();<br />

}<br />

}<br />

public class Super {<br />

public static void main( String argv[] ){<br />

C1 c1 = new C4();<br />

c1.m();<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 101<br />

2.2.2 Operationelle Semantik einer Untersprache von<br />

Java<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 102<br />

Abstrakte Syntax von Java-KE<br />

Package = pack(PackId ImportList TypeDeclList)<br />

ImportList = list of PackId<br />

TypeDeclList = list of TypeDecl<br />

TypeDecl = ClassDecl(CTypeId CTypeId ITypeIdList ClassBody)<br />

| InterfaceDecl(ITypeId ITypeIdList InterfaceBody)<br />

ClassBody = list of MemberDecl<br />

MemberDecl = FieldDecl(Type FieldId)<br />

| MethodDecl(MethodSig Statement)<br />

InterfaceBody = list of MethodSig<br />

MethodSig = Sig(Type MethodId Type)<br />

Type = booleanT () | intT () | nullT () | ct(CTypeId) | it(ITypeId)<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 103<br />

Statement = block(Type VarId Statement)<br />

| fread(VarId VarId FieldId)<br />

| fwrite(VarId FieldId VarId)<br />

| cassign(VarId Type Exp)<br />

| new(VarId CTypeId)<br />

| seq(Statement Statement)<br />

| if (Exp Statement Statement)<br />

| while(Exp Statement)<br />

| catch(Statement CTypeId VarId Statement)<br />

//try − body CTypeId = NullPExc or CastExc<br />

| invoc(VarId VarId MethodId Exp)<br />

| call(VarId CTypeId MethodId Exp)<br />

Exp = ic(Int) | bc(Bool) | null() | id(VarId)<br />

| unary(UnOp Exp) | binary(Exp BinOp Exp)<br />

PackId, FieldId, MethodId, CTypeId, ITypeId und VarId sind einfache<br />

Sorten.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 104<br />

Kontextabhängige Syntax von Java-KE<br />

Kontextbedingungen:<br />

1. Kontextbedingungen wie in Java. Ausnahme: Die<br />

Methode main zum Starten eines Programmes hat genau<br />

einen Parameter des Typs int und liefert einen Wert des<br />

Typs int.<br />

2. Programme haben eine Klasse Object mit mindestens<br />

einer Methode (in diesem Fall ist der zweite Parameter von<br />

ClassDecl auch Object, ohne dass dies den Schluss<br />

erlaube, Object sei ein echter Subtyp von sich selbst).<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 105<br />

3. Programme haben die Klassen CastExc und NullPExc.<br />

4. Der CTypeId in einer call Anweisung muss die<br />

Superklasse bezeichnen, in der die Supermethode definiert<br />

ist.<br />

5. Deklarierte Variablen dürfen nicht res oder exc genannt<br />

werden. res ist implizit deklariert und sichtbar in jeder<br />

Anweisung, wie auch par und this.<br />

exc darf in Anweisungen nicht verwendet werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 106<br />

6. FieldIds sind eindeutig, d.h. Attribute in verschiedenen<br />

Klassen müssen unterschiedlich benannt werden (z.B.<br />

durch Voranstellung des CTypeId der enthaltenden<br />

Klasse).<br />

7. Typnamen müssen eindeutig sein (zum Beispiel darf ein<br />

Paket P nur Pakete importieren, deren Typnamen sich von<br />

denen, die in P deklariert sind, unterscheiden).<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 107<br />

Definition(Programmbereich in Java-KE):<br />

Jedes Paket P definiert einen Programmbereich, der<br />

• P enthält sowie<br />

• alle direkt oder indirekt von P importierten Pakete.<br />

Bemerkung:<br />

Für jedes Programmelement (Deklaration, Anweisung) gibt<br />

es einen minimalen Programmbereich, in dem es enthalten<br />

ist.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 108<br />

Statische Semantik<br />

Die statische Semantik liefert die Begriffe, um die<br />

Ausführungszustände von Programmen zu beschreiben.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 109<br />

: T ype × T ype → Bool // Subtyprelation<br />

≺ : T ype × T ype → Bool // echte Subtyprelation<br />

ObjId : eine passende Menge von Objektbezeichnern<br />

InstVar : eine passende Menge von typisierten Instanzvariablen<br />

DeclMethId : eindeutige Namen für die implementierten Methoden<br />

VirtMethId : eindeutige Namen für die virtuellen Methoden<br />

ProgPart : DeclMethId | VirtMethId | Statement@<br />

wobei Statement@ die Menge der Anweisungsknoten des<br />

kleinsten umgebenden Programmbereichs bezeichnet.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 110<br />

Bemerkungen:<br />

• Eine implementierte Methode ist eine Methode, deren<br />

Rumpf in einer Klasse deklariert ist.<br />

• Eine virtuelle Methode ist eine Methode, die in einem Typ<br />

deklariert ist.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 111<br />

Die Funktion vis : ProgPart → POW (VarId) liefert für<br />

jeden Programmteil pp die Menge der sichtbaren VarIds.<br />

Für Anweisungen c gilt: vis(c) enthält res, exc, this, par<br />

und die deklarierten lokalen Variablen.<br />

Für Methodenabstraktionen m gilt:<br />

vis(m) = {this, par, exc}<br />

Die Funktion typs : PackId → POW (Type) liefert für jedes<br />

Paket M die Menge der Typen, die in M bekannt sind.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 112<br />

Werte und Abkürzungen von Java-KE<br />

Value = b(Bool)<br />

| i(Int)<br />

| null()<br />

| ref (CTypeId ObjId)<br />

typ : Value → Type // Typ eines Wertes<br />

rtyp : ProgPart → Type<br />

// Ergebnistyp einer Methode oder Typ von res<br />

styp : InstVar → Type //Typ einer Instanzvariablen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 113<br />

styp : VarId × ProgPart → Type<br />

// deklarierter Typ einer Variablen sichtbar in ProgPart;<br />

// styp(exc,pp)=ct(Object); ansonsten nicht determiniert<br />

impl : T ype × MethodId → DeclMethId<br />

// impl(T,m) ist nicht determiniert, wenn T keine<br />

// Implementierung einer Methode m enthält.<br />

vm : T ype × MethodId → V irtMethId<br />

// vm(T,m) ist nicht determiniert, wenn m nicht in T ist<br />

body : DeclMethId → Statement<br />

vmid : V irtMethId → MethodId<br />

. : V alue × F ieldId → InstV ar<br />

//v.f liefert die Instanzvariable f des Objektes v;<br />

//ansonsten nicht determiniert<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 114<br />

Modellierung des Objektspeichers<br />

〈 := 〉 : Store × InstVar × Value → Store<br />

〈 〉 : Store × CTypeId → Store<br />

( ) : Store × InstVar → Value<br />

new : Store × CTypeId → Value<br />

alive : Store × Value → Value<br />

IV1 = IV2 ⇒ OS〈IV1 := X 〉(IV2 ) = OS(IV2 )<br />

OS〈T 〉(IV ) = OS(IV )<br />

alive(OS〈IV := Y 〉, X ) ⇔ alive(OS, X )<br />

alive(OS〈T 〉, X ) ⇔ alive(OS, X ) ∨ X = new(OS, T )<br />

alive(OS, OS(IV ))<br />

typ(new(OS, T )) = ct(T )<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 115<br />

Zustände von Variablen und Objektspeicher<br />

State : (VarId → Value) × ({$} → Store)<br />

Zustände werden üblicherweise mit S, SQ, SR bezeichnet.<br />

Die Anwendung eines Zustandes auf ein VarId v wird mit<br />

S(v) bezeichnet, auf die Speichervariable $ mit S($).<br />

Eine Änderung von S in v oder $ wird mit S[v := E] bzw.<br />

S[$ := E] bezeichnet.<br />

Sei e ein Programmausdruck der Sorte Exp. Dann<br />

bezeichnet e[S] die Auswertung von e in S.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 116<br />

Für jeden Typ wird ein initialer Wert vorausgesetzt:<br />

init : T ype → V alue<br />

typ(init(T )) T<br />

T kann ein Schnittstellentyp oder ein Basistyp sein.<br />

init(T ) kann gleich null() sein.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 117<br />

Dynamische Semantik<br />

Wir beschreiben die dynamische Semantik operationell.<br />

Um nicht auf statische Methoden zurückgreifen zu müssen,<br />

wird die Programmausführung dadurch gestartet, dass ein<br />

Objekt der Startklasse Main erzeugt wird. Die Klasse Main<br />

muss eine Methode main haben, die beim Start mit dem<br />

Eingabeargument aufgerufen wird (siehe unten). Folgende<br />

Anweisungen erläutern, was beim Programmstart passiert:<br />

int input, output;<br />

Main mainvar;<br />

mainvar = new Main();<br />

output = mainvar. main( input );<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 118<br />

Die Semantik wird durch Relationen mit folgender Signatur<br />

ausgedrückt:<br />

psem : State × P rogram × int × int × State<br />

ssem : State × Statement@ × State<br />

Die Relationen werden induktiv durch Regeln (s.u.) definiert.<br />

In den Regeln schreiben wir<br />

SP : c → SQ anstatt ssem(SP, c, SQ)<br />

SP :: p(i) → r, SQ anstatt psem(SP, p, i, r, SQ)<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 119<br />

ssem(SP, c, SQ) bedeutet, dass die Ausführung von c mit<br />

Vorzustand SP terminiert und in den Nachzustand SQ führt.<br />

SQ(exc) = null bedeutet, dass die Ausführung von c normal<br />

beendet wurde. Andernfalls endete die Ausführung abrupt<br />

mit einer Ausnahme.<br />

Bemerkung:<br />

Die Definition von ssem setzt keine Wohltypisiertheit der<br />

Zustände voraus. Solche Eigenschaften werden ausgehend<br />

von der Definition von ssem untersucht werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 120<br />

S[this := new(S($), Main), par := IN , exc := null, res = init(int), $ := S($)〈Main〉]<br />

: body(Main@main) → SQ<br />

S :: prog(IN ) → SQ(res), SQ<br />

S(y) = null<br />

S : x = y.a; → S[x := S($)(S(y).a)]<br />

Bemerkung:<br />

Der Gebrauch dieser Regel setzt voraus, dass S(exc) = null<br />

im Vorzustand, ansonsten würde eine Ausnahme, die nicht<br />

vorgekommen ist, im Nachzustand sichtbar sein.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 121<br />

S(y) = null<br />

S : x = y.a; → S[$ := S($)〈NullPExc〉, exc := new(S($), NullPExc)]<br />

S(x) = null<br />

S : x.a = e; → S[$ := S($)〈S(x).a := e[S]〉]<br />

S(x) = null<br />

S : x.a = e; → S[$ := S($)〈NullPExc〉, exc := new(S($), NullPExc)]<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 122<br />

typ(e[S]) T<br />

S : x = (T )e; → S[x := e[S]]<br />

typ(e[S]) T<br />

S : x = (T )e; → S[$ := S($)〈CastExc〉, exc := new(S($), CastExc)]<br />

true<br />

S : x = newT (); → S[x := new(S($), T ), $ := S($)〈T 〉]<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 123<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

S : s1 → SQ, SQ(exc) = null, SQ : s2 → SR<br />

S : s1 s2 → SR<br />

S : s1 → SQ, SQ(exc) = null<br />

S : s1 s2 → SQ<br />

e[S], S : s1 → SQ<br />

S : if (e){s1 }else{s2 } → SQ


2.2 Semantik objektorientierter Sprachen 124<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

¬e[S], S : s2 → SQ<br />

S : if (e){s1 }else{s2 } → SQ<br />

¬e[S]<br />

S : while(e){s} → S<br />

e[S], S : s → SQ, SQ(exc) = null<br />

S : while(e){s} → SQ


2.2 Semantik objektorientierter Sprachen 125<br />

e[S], S : s → SQ, SQ(exc) = null, SQ : while(e){s} → SR<br />

S : while(e){s} → SR<br />

S : s0 → SQ, SQ(exc) = null<br />

S : try{s0 }catch(T e){s1 } → SQ<br />

S : s0 → SQ, SQ(exc) = null, typ(SQ(exc)) T<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

S : try{s0 }catch(T e){s1 } → SQ


2.2 Semantik objektorientierter Sprachen 126<br />

S : s0 → SQ, SQ(exc) = null, typ(SQ(exc)) T ,<br />

SQ[e := SQ(exc), exc := null] : s1 → SR<br />

S : try{s0 }catch(T e){s1 } → SR<br />

S[v := init(T )] : s → SQ<br />

S : {T v; s} → SQ<br />

S(y) = null, typ(S(y)) styp(y ′ , x = y.m(e); ), DMI = impl(typ(S(y)), m),<br />

S[this := S(y), par := e[S], res := init(rtyp(DMI ))] : body(DMI ) → SQ<br />

S : x = y.m(e); → S[x := SQ(res), $ := SQ($), exc := SQ(exc)]<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 127<br />

S(y) = null<br />

S : x = y.m(e); → S[$ := S($)〈NullPExc〉, exc := new(S($), NullPExc)]<br />

S[par := e[S], res := init(rtyp(impl(T , m))] : body(impl(T , m)) → SQ<br />

S : x = superT.m(e); → S[x := SQ(res), $ := SQ($), exc := SQ(exc)]<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 128<br />

Ausführung mit wohltypisierten Zuständen<br />

Argumente, warum ssem nicht von vornherein für<br />

wohltypisierte Zustände definiert wurde:<br />

• Ein Zustand ist nur im Kontext einer Anweisung<br />

wohltypisiert; deswegen wird die Quantifikation über<br />

Zustände problematisch, wenn versucht wird, Zustände<br />

typkorrekt zu machen.<br />

• Regeln auf einfache Art formulieren und dann<br />

Eigenschaften über sie beweisen<br />

• Typsicherheit als Eigenschaft beweisbar<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 129<br />

wts : Store → Bool<br />

wts(OS) ⇔ ALL InstVar IV : typ(OS(IV )) styp(IV )<br />

wt, wtp, wtr : State × ProgPart → Bool<br />

wt(S, pp) ⇔ S(this) = null ∧ wts(S($))∧<br />

∧ ALL VarId V : V ∈ vis(pp) ⇒ typ(S(V )) styp(V , pp)<br />

wtp(S, pp) ⇔ wt(S, pp) ∧ S(exc) = null<br />

wtr(S, pp) ⇔ wt(S, pp) ∧ typ(S(res)) rtyp(pp)<br />

wtr wird nur für den Nachzustand von Methoden benötigt.<br />

Für eine Anweisung gilt: wtr(S, c) ⇔ wt(S, c).<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 130<br />

Ausgehend von ssem wird eine semantische Relation<br />

definiert, die auch für Methodenabstraktionen gilt:<br />

sem : State × ProgPart × State<br />

sem(S, c, SQ) ⇔ wtp(S, c) ∧ ssem(S, c, SQ)<br />

sem(S, T @m, SQ) ⇔ wtp(S, T @m)∧<br />

∧ sem(S[res := init(rtyp(T @m))], body(T @m), SQ)<br />

sem(S, T : m, SQ) ⇔ wtp(S, T : m)∧<br />

∧ sem(S, impl(typ(S(this)), m), SQ)<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 131<br />

2.2.3 Zur Theorie strukturell operationeller<br />

Semantikdefinitionen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 132<br />

Definition(big step SOS):<br />

Eine Semantikdefinition der oben demonstrierten Art nennt<br />

man<br />

• großschrittig, weil zu einer Regelanwendung im Allg. viele<br />

Ausführungsschritte gehören;<br />

• strukturell, weil sie der syntaktischen Programmstruktur<br />

folgt;<br />

• operationell, weil sie die Ausführung des Programms<br />

modelliert.<br />

(big step structural operational semantics, big step SOS)<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 133<br />

Es gibt zwei Arten, eine SOS-Spezifikation zu lesen:<br />

1. Liste von Inferenzregeln zur Ausführung von Programmen:<br />

sem(S, pp, SQ) gilt genau dann, wenn es eine endliche<br />

Herleitung für sem(S, pp, SQ) mit den Regeln gibt.<br />

2. Notationelle Kurzform für eine rekursive<br />

Prädikatdefinition: Spezifikation eines Prädikats als<br />

schwächsten Fixpunkt.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 134<br />

Beispiel(rekursive Prädikatdefinition):<br />

typ(e[S]) T<br />

ssem(S, x = (T )e; , S[x := e[S]])<br />

ssem(S, s1 , SQ), SQ(exc) = null, ssem(SQ, s2 , SR)<br />

ssem(S, s1 s2 , SR)<br />

ssem(S, c, SR) ⇔<br />

...<br />

∨ ((c hat die Form x = (T )e; ) ∧ typ(e[S]) T ∧ SR = S[x := e[S]] )<br />

...<br />

∨ ((c hat die Form s1 s2 )∧<br />

∃SQ : ssem(S, s1 , SQ) ∧ SQ(exc) = null ∧ ssem(SQ, s2 , SR)<br />

)<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 135<br />

Lemma:<br />

Java-KE ist deterministisch, d.h. ssem definiert eine partielle<br />

Funktion, und es gilt für alle Zustände S, SQ, SR, pp:<br />

ssem(S, pp, SQ) und ssem(S, pp, SR) impliziert SQ = SR<br />

Beweisskizze:<br />

Wir zeigen per Induktion nach n:<br />

Sind zwei Herleitungsbäume HQ, HR mit ssem(S, pp, SQ)<br />

bzw. ssem(S, pp, SR) als Wurzeln gegeben, tiefe(HQ) ≤ n<br />

und tiefe(HR) ≤ n, dann gilt HQ = HR und insbesondere<br />

SQ = SR.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 136<br />

Induktionsanfang n = 1:<br />

Bei gegebenem S und pp gibt es genau eine Instanz der<br />

Regeln ohne Vorkommen von sem in dem Antecedent.<br />

Induktionsschritt n → n + 1:<br />

Seien HQ und HR zwei Herleitungsbäume mit<br />

ssem(S, pp, SQ) bzw. ssem(S, pp, SR) als Wurzeln und<br />

o.E.d.A. tiefe(HQ) = n + 1 und tiefe(HR) ≤ n + 1 .<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 137<br />

Fall 1:<br />

S und pp bestimmen die letzte angewendete Regel r in HR<br />

und HQ.<br />

1.1: Der Antecedent von r enthält maximal ein rekursives<br />

Vorkommen von ssem. Dann bestimmen S und pp den<br />

Vorzustand S0 und den Programmteil pp0 für dieses<br />

Vorkommen (in allen Regeln nur funktionale<br />

Abhängigkeiten).<br />

Nach Induktionsvoraussetzung muss dann der Nachzustand<br />

des zugehörigen Astes der beiden Herleitungen gleich sein.<br />

Damit ist aber auch SQ = SR.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 138<br />

1.2: Der Antecedent von r enthält zwei rekursive<br />

Vorkommen von ssem. Dann bestimmen S und pp den<br />

Vorzustand S0 und den Programmteil pp0 für das erste<br />

Vorkommen (in allen Regeln nur funktionale<br />

Abhängigkeiten).<br />

Nach Induktionsvoraussetzung muss dann der Nachzustand<br />

des zugehörigen Astes der beiden Herleitungen gleich sein.<br />

Damit ist der Vorzustand für das zweite rekursive<br />

Vorkommen gleich. Die Induktionsvoraussetzung liefert<br />

wieder, dass die Nachzustände gleich sind und damit auch<br />

SQ = SR. Entsprechend für weitere rekursive Vorkommen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 139<br />

Fall 2:<br />

Gemäß S und pp kommen zwei oder drei Regeln als letzte<br />

Regeln in HR und HQ in Frage. In allen diesen Regeln ist der<br />

erste Antecedent gleich und – wie unter Fall 1 erläutert –<br />

ergibt sich gemäß Induktionsvoraussetzung ein gleicher<br />

Nachzustand zum ersten Antecedenten. Entsprechend<br />

angewendet auf die weiteren Antecedenten ergibt sich, dass<br />

die letzten Regeln in HR und HQ gleich sein müssen und<br />

SR=SQ.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.2 Semantik objektorientierter Sprachen 140<br />

Bemerkung:<br />

Der Beweis des obigen Lemmas benutzt die<br />

Inferenzregel-Interpretation der Semantik. Bei der<br />

Fixpunktinterpretation müsste eine andere Beweistechnik<br />

verwendet werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 141<br />

2.3 Eigenschaften objektorientierter<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

Programme


2.3 Eigenschaften objektorientierter Programme 142<br />

Übersicht<br />

Dieser Abschnitt gibt eine kurze<br />

Programmeigenschaften.<br />

Wir unterscheiden:<br />

• Zusicherungen<br />

• Anweisungsspezifikationen<br />

• Ablaufeigenschaften<br />

• Schnittstelleneigenschaften<br />

• weitere Eigenschaften<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

Übersicht über relevante


2.3 Eigenschaften objektorientierter Programme 143<br />

Definition(Programmvariable):<br />

Eine Programmvariable ist ein lokale Variable, ein<br />

Parameter, eine Instanzvariable oder eine Klassenvariable.<br />

Programmvariablen speichern Werte.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 144<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

2.3.1 Zusicherungen


2.3 Eigenschaften objektorientierter Programme 145<br />

Sei S eine Programmstelle in einem Programm P.<br />

Eine Zusicherung an der Stelle S ist eine Eigenschaft, die<br />

immer gelten soll, wenn die Ausführung S erreicht.<br />

Zusicherungen lassen sich mittels eines Ausdrucks oder einer<br />

Formel über den an S sichtbaren Größen spezifizieren.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 146<br />

Beispiel(Zusicherungen):<br />

1. Einfache Eigenschaft:<br />

...<br />

C cobj = new C(...);<br />

assert cobj.x != null ;<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 147<br />

2. Schleifeninvariante:<br />

public static int isqrt( int x ){<br />

int count = 0, sum = 1;<br />

while (sum


2.3 Eigenschaften objektorientierter Programme 148<br />

3. Komplexere Eigenschaft im Kontext vom AWT:<br />

...<br />

Container c;<br />

Button b;<br />

...<br />

c.remove(b);<br />

assert !EX Container cex: !EX int i:<br />

cex.getComponents()[i] == b;<br />

...<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 149<br />

Bemerkung:<br />

• Zusicherungen können Aussagen über den Zustand von<br />

Programmvariablen machen.<br />

• Werden Java-Ausdrücke zur Spezifikation verwendet,<br />

sollten diese seiteneffektfrei sein.<br />

• Zusicherungen können verwendet werden, um<br />

Vorbedingungen von Methoden zu beschreiben.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 150<br />

2.3.2 Anweisungsspezifikationen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 151<br />

Anweisungsspezifikationen beschreiben das Verhalten einer<br />

Anweisung, Prozedur oder Methode (im Folgenden nur für<br />

Anweisungen formuliert).<br />

Wir unterscheiden:<br />

• Vor- und Nachbedingungsspezifikationen<br />

• Ereignisspezifikation<br />

• Spezifikation von Terminierung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 152<br />

Vor- und Nachbedingungsspezifikationen<br />

Im Unterschied zu Zusicherungen beziehen sich Vor- und<br />

Nachbedingungsspezifikationen auf zwei Zustände.<br />

Beispiel(Vor- und Nachbedingungsspezifikationen):<br />

1. Ohne Verwendung der Variablenwerte des Vorzustands<br />

pre x>=0 && count==0 && sum == 1<br />

while (sum


2.3 Eigenschaften objektorientierter Programme 153<br />

2. Mit Verwendung der Variablenwerte des Vorzustands<br />

pre a == X<br />

post a == X + n;<br />

void incrA ( int n ) {<br />

a += n;<br />

}<br />

Alternativ:<br />

pre true<br />

post a == \old(a) + n;<br />

void incrA ( int n ) {<br />

a += n;<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 154<br />

Ereignisspezifikationen<br />

Ereignisspezifikationen machen Aussagen über Ereignisse, die<br />

bei der Ausführung von Anweisungen auftreten oder nicht<br />

auftreten dürfen.<br />

Typische Ereignisse beziehen sich auf:<br />

• Auftreten von Ausnahmen<br />

• Aufrufe von Methoden<br />

• Modifikation von Variablen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 155<br />

Beispiel(Ereignisspezifikationen):<br />

modifiable this.width, this.height ;<br />

public void resize(int width, int height) {<br />

...<br />

}<br />

Bedeutung:<br />

Aufrufe von resize haben nur die Erlaubnis, die<br />

Instanzvariablen width, height des Zielobjektes zu ändern.<br />

Andere Instanzvariablen dürfen nicht modifiziert werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 156<br />

Bemerkung:<br />

Bei Abschwächung der Bedeutung lassen sich<br />

Ereignisspezifikationen durch Vor- und<br />

Nachbedingungsspezifikationen ersetzen:<br />

pre $(IV) = X ;<br />

post $(IV) = X \/ IV = this.width \/ IV = this.height ;<br />

public void resize(int width, int height) {<br />

...<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 157<br />

Spezifikation von Terminierung<br />

Terminierung wird meist implizit im Zusammenhang mit<br />

Vorbedingungen spezifiziert. Eine Spezifikation<br />

pre <br />

post <br />

<br />

bedeutet dann, wenn die Vorbedingung erfüllt ist, terminiert<br />

die Anweisung.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 158<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

2.3.3 Ablaufeigenschaften


2.3 Eigenschaften objektorientierter Programme 159<br />

Die Sequenz der Zustände, die sich bei der Ausführung eines<br />

Programms ergeben, nennen wir einen Ablauf. Dabei können<br />

die Schritte von Zustand zu Zustand mehr oder weniger<br />

umfangreich sein.<br />

Ggf. kann ein Ablauf auch mit zusätzlicher Information<br />

versehen sein (z.B. Aufruf und Verlassen von Methode).<br />

Eigenschaften, die sich auf Abläufe beziehen, nennen wir<br />

Ablaufeigenschaften.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 160<br />

Wir unterscheiden:<br />

• Invarianten<br />

• zustandsübergreifende Eigenschaften<br />

• temporale Eigenschaften<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 161<br />

Invarianten<br />

Invarianten sind Eigenschaften, die grundsätzlich in allen<br />

Zuständen gelten sollen.<br />

Beispiel(Invarianten):<br />

1. Typinvarianten :<br />

Das Typsystem garantiert üblicherweise, dass in allen<br />

Zuständen gilt:<br />

Speichert eine Programmvariable V einen Wert W, dann ist<br />

der Typ von W ein Subtyp des (statischen) Typs von V.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 162<br />

2. Klasseninvarianten :<br />

Klassen können mit Klasseninvarianten annotiert werden.<br />

Die spezifizierte Eigenschaft sollte im Wesentlichen in allen<br />

Ausführungszuständen gelten, in denen das betreffende<br />

Objekt lebt. (Mögliche Ausnahmen sind z.B. Zustände<br />

innerhalb der Ausführungszustände privater Methoden.)<br />

Beispiel(Klasseninvarianten):<br />

class C {<br />

//@ invariant myobject != null;<br />

SomeObject myobject;<br />

...<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 163<br />

3. Klassenübergreifende Invarianten :<br />

• zur Beschreibung von Objektstrukturen, die aus Objekten<br />

mehrerer Klassen bestehen<br />

• Kapselungseigenschaften, z.B. die Garantie, dass<br />

bestimmte Objekte nur von Objekten des eigenen Pakets<br />

referenziert werden<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 164<br />

Zustandsübergreifende Eigenschaften<br />

Eine zustandsübergreifende Eigenschaft (engl. history<br />

property) bezieht sich auf mehrere Zustände. Wir<br />

konzentrieren uns hier auf zustandsübergreifende<br />

Eigenschaften, die sich auf zwei Zustände beziehen (binäre<br />

Eigenschaft).<br />

Eine binäre Eigenschaft E gilt in einem Ablauf A, wenn E für<br />

alle Paare (Z1, Z2) von (sichtbaren) Zuständen aus A gilt.<br />

Zustandsübergreifende Eigenschaften sind die einfachste<br />

Form, um die Entwicklungen in Abläufen zu beschreiben.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 165<br />

Beispiel(Zustandsübergreifende Eigenschaften):<br />

1. Eine Variable x verändert nicht ihren Wert:<br />

constraint x == \old(x) ;<br />

oder<br />

constraint if \old(x)!= null then x == \old(x) ;<br />

2. Der Wert einer ganzzahligen Variablen nimmt nicht ab:<br />

constraint \old(x)


2.3 Eigenschaften objektorientierter Programme 166<br />

Temporale Eigenschaften<br />

Temporale Eigenschaften können sich auf beliebig viele<br />

Zustände beziehen und schließen Existenzaussagen sowie<br />

Aussagen über Teile des Ablaufs ein.<br />

Insbesondere umfassen sie: Lebendigkeitseigenschaften<br />

(etwas Gutes wird in der Zukunft passieren)<br />

Sie stellen eine Verallgemeinerung von Invarianz und<br />

zustandsübergreifenden Aussagen dar.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 167<br />

Beispiel(Temporale Eigenschaften):<br />

1. Zustandsbezogene temporale Eigenschaften<br />

sometimes x != null<br />

x == 0 until a == 8<br />

2. Ereignisbezogene temporale Eigenschaften<br />

call(m) sometimes call(n)<br />

Bemerkung:<br />

Temporale Eigenschaften sind insbesondere im<br />

Zusammenhang mit parallelen Programmen wichtig.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 168<br />

2.3.4 Schnittstelleneigenschaften<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 169<br />

Schnittstelleneigenschaften unterscheiden sich von anderen<br />

Programmeigenschaften dadurch, dass sie sich nicht oder<br />

nur teilweise auf die Implementierung beziehen dürfen.<br />

Schnittstelleneigenschaften benötigen Abstraktion.<br />

Beispiel(Schnittstelleneigenschaften):<br />

package org.jmlspecs.samples.stacks;<br />

//@ model import org.jmlspecs.models.*;<br />

public abstract class UnboundedStack {<br />

/*@ public model JMLObjectSequence theStack<br />

@ initially theStack != null && theStack.isEmpty();<br />

@*/<br />

//@ public invariant theStack != null;<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 170<br />

/*@ public normal_behavior<br />

@ requires !theStack.isEmpty();<br />

@ modifies theStack;<br />

@ ensures theStack.equals(\old(theStack.trailer()));<br />

@*/<br />

public abstract void pop( );<br />

/*@ public normal_behavior<br />

@ modifies theStack;<br />

@ ensures theStack.equals(\old(theStack.insertFront(x)));<br />

@*/<br />

public abstract void push(Object x);<br />

/*@ public normal_behavior<br />

@ requires !theStack.isEmpty();<br />

@ ensures \result == theStack.first();<br />

@*/<br />

public abstract Object top( );<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 171<br />

Bemerkung: Techniken zur Spezifikation der abstrakten<br />

Datenstruktur, die der Schnittstellenspezifikation zugrunde<br />

liegt:<br />

• seiteneffektfreies, auf Verständnis optimiertes<br />

Java-Programm<br />

• mathematische Modellierung<br />

• algebraische oder logische Theorie<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.3 Eigenschaften objektorientierter Programme 172<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

2.3.5 Weitere Eigenschaften


2.3 Eigenschaften objektorientierter Programme 173<br />

• nicht funktionale Eigenschaften:<br />

◦ Effizienz<br />

◦ Portabilität<br />

◦ Skalierbarkeit<br />

◦ ...<br />

• Kapselungseigenschaften:<br />

◦ Kapselungsbereiche<br />

◦ Sicherheitsgarantien<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 174<br />

2.4 Modularität und Kapselung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 175<br />

2.4.1 Modularität und modulare Spezifikation<br />

2.4.2 Kapselung und Schnittstellenbildung<br />

2.4.3 Realisieren von Kapselung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 176<br />

2.4.1 Modularität und modulare Spezifikation<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 177<br />

Definition(Modulare Programmierung):<br />

Modulare Programmierung bedeutet:<br />

1. Ergebnis der Programmierung sind Programmmodule,<br />

nicht notwendig vollständige Programme.<br />

2. Die Implementierung eines Moduls kann andere Module<br />

benutzen: Deren Implementierung muss nicht notwendig<br />

bekannt sein.<br />

3. Der Anwendungskontext eines Moduls ist zur<br />

Entwicklungszeit im Allg. nicht bekannt.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 178<br />

Definition(Modulare Spezifikation):<br />

Eine Spezifikationstechnik für modulare Programme heißt<br />

modular, wenn sie folgende Eigenschaften besitzt:<br />

1. Sie ermöglicht es, Modulschnittstellen zu spezifizieren.<br />

2. Die Spezifikation S(M) eines Moduls M reicht aus, um M<br />

benutzen zu können, d.h.:<br />

◦ S(M) beschreibt die relevanten Eigenschaften von M.<br />

◦ S(M) reicht aus, um die Korrektheit von Modulen zu zeigen, die M<br />

benutzen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 179<br />

3. Die Korrektheit einer Modulspezifikation S(M) lässt sich<br />

ohne Kenntnis möglicher Anwendungskontexte von M<br />

zeigen, d.h. mit Kenntnis:<br />

◦ der Spezifikationen verwendeter Module<br />

◦ der Implementierung von M.<br />

4. Die Korrektheit einer Modulspezifikation S(M) bleibt in<br />

jedem zulässigen Anwendungskontext erhalten.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 180<br />

Beispiel(Problematik modularer Spezifikationen):<br />

package somepack;<br />

public class C {<br />

protected int a = 7;<br />

//@ ensures \result >= 7;<br />

public int getA() { return a; }<br />

}<br />

Betrachte ein Modul M, das Objekte der Klasse C als<br />

Parameter bekommt:<br />

• Der Spezifikation entsprechend kann man davon ausgehen,<br />

dass getA immer eine Zahl größer oder gleich 7 liefert.<br />

• Diese Eigenschaft kann bewiesen und in Beweisen<br />

verwendet werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 181<br />

Erweiterung von C:<br />

package someotherpack;<br />

import somepack.*<br />

public class D extends C {<br />

public void decrA() { a--; }<br />

}<br />

Nun kann es passieren, dass Modul M statt eines C-Objekts<br />

ein D-Objekt erhält. Für D-Objekte gilt aber nicht die<br />

Eigenschaft von getA, und die Beweise, die sich auf die<br />

Korrektheit von M abgestützt haben, werden ungültig.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 182<br />

Lösungsansatz:<br />

• klare Schnittstellenbildung und Kapselung<br />

• Spezifikation der relevanten Eigenschaften<br />

• Subtypen müssen Spezifikation der Supertypen erfüllen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 183<br />

2.4.2 Kapselung und Schnittstellenbildung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 184<br />

Information Hiding und Kapselung (engl. encapsulation)<br />

werden häufig synonym bebraucht. In unserer Begriffsbildung<br />

ist Kapselung schärfer gefasst als Information Hiding.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 185<br />

Definition(Information Hiding):<br />

Information Hiding ist eine Technik, um die Abhängigkeiten<br />

zwischen Klassen und Paketen zu reduzieren:<br />

• Der Anbieter stellt nur die Information (öffentlich) zur<br />

Verfügung, die für die Benutzung notwendig ist.<br />

• Der Benutzer nutzt nur die öffentliche Information.<br />

Dementsprechend bezieht sich Information Hiding vorrangig<br />

auf Software, also statische Aspekte.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 186<br />

Bemerkung:<br />

• In der OO-Programmierung gibt es zwei Arten von<br />

Benutzung:<br />

◦ Vererbungsnutzung<br />

◦ Anwendungsnutzung<br />

• Information Hiding ermöglicht:<br />

◦ konsistente Namensänderungen in versteckten Programmteilen<br />

(unkritisch);<br />

◦ Veränderungen an versteckten Implementierungsteilen, soweit sie<br />

keine Auswirkungen auf die öffentliche Funktionalität haben<br />

(kritisch).<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 187<br />

Beispiel(Information Hiding):<br />

public class MyList {<br />

private int leng;<br />

private LinkedList theList;<br />

}<br />

public int length() { return leng; }<br />

...<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 188<br />

Definition(Kapselung):<br />

Kapselung ist eine Technik zur Strukturierung des<br />

Zustandsraumes ablaufender Programme.<br />

Ziel ist es, durch Bildung von Kapseln mit klar definierten<br />

Zugriffsschnittstellen die Daten- und Strukturkonsistenz zu<br />

gewährleisten.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 189<br />

Kapseln können sein:<br />

• einzelne Objekte<br />

• zusammenhängende Objekte<br />

• eine Klasse (mit allen ihren Objekten)<br />

• alle Klassen in einer Vererbungshierarchie<br />

• Pakete (mit allen Klassen und deren Objekten)<br />

• mehrere Pakete<br />

Kapselung setzt eine Festlegung der Kapselgrenzen und der<br />

Schnittstellen an den Kapselgrenzen voraus.<br />

Kapselung bezieht sich vorrangig auf dynamische Aspekte.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 190<br />

Bemerkung:<br />

• Kapselung spielt vor allem eine wichtige Rolle im<br />

Zusammenhang mit Verteilung und Parallelität.<br />

• Kapselung wird mit Mitteln des Information Hiding<br />

erreicht.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 191<br />

Beispiel(Kapseln und Schnittstellen):<br />

1. Beschränkung auf privaten Zugriff garantiert keine<br />

Kapselung von Objekten:<br />

public class Privat {<br />

private int a;<br />

private Privat nachbar;<br />

}<br />

public void incrA(){<br />

a++;<br />

nachbar.a++;<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 192<br />

2. Die Java-Klasse LinkedList realisiert Kapseln mit einem<br />

LinkedList-Objekt und ggf. mehreren ListIterator-Objekten<br />

an der Schnittstelle:<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 193<br />

LinkedList<br />

Entry<br />

ListIterator<br />

Entry Entry Entry<br />

Object<br />

Object<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

3<br />

0<br />

Object<br />

ListIterator<br />

2


2.4 Modularität und Kapselung 194<br />

public class LinkedList extends AbstractSequentialList<br />

implements List, Cloneable, java.io.Serializable<br />

{<br />

public LinkedList();<br />

public LinkedList(Collection c);<br />

public Object getFirst(); public Object getLast();<br />

public Object removeFirst(); public Object removeLast();<br />

public void addFirst(Object o); public void addLast(Object o);<br />

public boolean contains(Object o); public int size();<br />

...<br />

public ListIterator listIterator(int index);<br />

... }<br />

public interface ListIterator extends Iterator {<br />

boolean hasNext(); Object next();<br />

boolean hasPrevious(); Object previous();<br />

int nextIndex(); int previousIndex();<br />

void remove();<br />

void set(Object o); void add(Object o); }<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 195<br />

3. Sicherheitslücke in Java 1.1.1:<br />

public final class Class ... {<br />

...<br />

private Identity[] signers;<br />

...<br />

public Identity[] getSigners() {<br />

return signers;<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 196<br />

2.4.3 Realisieren von Kapselung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 197<br />

Programmiersprachen stellen Sprachkonstrukte fürs<br />

Information Hiding bereit; z.B. in Java:<br />

• Zugriffsrechte: public, default, protected, private<br />

• Einschränkung der Vererbung: final<br />

• Innere Klassen<br />

Damit lässt sich Kapselung realisieren. Eine direkte<br />

Unterstützung von Kapselung durch Sprachen gibt es nicht.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 198<br />

Beispiel(Kapselung):<br />

Die Klasse LinkedList implementiert Kapseln (s.o.) und<br />

schließt darin die Repräsentationsobjekte vom Typ Entry ein.<br />

Sie garantiert die folgenden Eigenschaften:<br />

a) Zugriff ist nur über LinkedList- und ListIterator-Objekte<br />

möglich.<br />

b) Benutzer besitzen keine Referenz auf Entry-Objekte.<br />

c) Zwei Kapseln haben keine Objekte gemeinsam.<br />

d) Die Eigenschaften bleiben bei Vererbung erhalten.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 199<br />

Realisierung:<br />

• Klasse Entry und Attribute mit Entry-Referenzen sind nur<br />

privat zugreifbar.<br />

• Klasse, die die Listeniteratoren implementiert, ist privat;<br />

deshalb lassen sich Iteratoren von außen nur über eine<br />

Methode von LinkedList-Objekten erzeugen.<br />

• Methoden der Schnittstellenobjekte geben keine<br />

Referenzen auf Repräsentationsobjekte heraus.<br />

Repräsentationsobjekte können nicht von außen<br />

eingeschleust werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 200<br />

Diskussion anhand der Implementierung:<br />

public class LinkedList ...<br />

{<br />

private ... Entry header = new Entry(null, null, null);<br />

private ... int size = 0;<br />

public LinkedList() { ... }<br />

... // public methods<br />

private Entry entry(int index) { ... }<br />

public ListIterator listIterator(int index) {<br />

return new ListItr(index);<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


}<br />

2.4 Modularität und Kapselung 201<br />

private class ListItr implements ListIterator {<br />

private Entry lastReturned = header;<br />

private Entry next;<br />

private int nextIndex;<br />

...<br />

}<br />

private static class Entry {<br />

Object element;<br />

Entry next;<br />

Entry previous;<br />

...<br />

}<br />

private Entry addBefore(Object o, Entry e) { ... }<br />

private void remove(Entry e) { ... }<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


2.4 Modularität und Kapselung 202<br />

Lesen Sie zu 2.4:<br />

A. Poetzsch-Heffter:<br />

Konzepte objektorientierter Programmierung,<br />

Springer-Verlag, 2000;<br />

Abschnitt 3.3, S. 157-171.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3. Techniken zum Prüfen<br />

objektorientierter Programme


3. Techniken zum Prüfen objektorientierter<br />

3.1 Einführung<br />

Programme<br />

3.1.1 Typinformation und ihre statische und dynamische<br />

Prüfung<br />

3.1.2 Typsicherheit<br />

3.2 Parametrische Typsysteme und Virtuelle Klassen<br />

3.3 Typsysteme zur Strukturierung von Objektgeflechten<br />

3.4 Erweiterte statische Prüfung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

204


3.1 Einführung 205<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

3.1 Einführung


3.1 Einführung 206<br />

Ein Typ beschreibt Eigenschaften von Werten bzw. Objekten<br />

(Beispiele: int, Object, LinkedList〈A〉).<br />

Typisierung bedeutet die Annotierung von<br />

Programmelementen mit Typen:<br />

• Ausdrücke: Jede Auswertung liefert einen Wert vom Typ<br />

des Ausdrucks.<br />

• Prozeduren/Methoden: Wenn die aktuellen Parameter den<br />

richtigen Typ haben, ist das Ergebnis vom Ergebnistyp.<br />

• Variablen: Eine Variable enthält nur Werte von ihrem Typ.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 207<br />

Typisierung ist eine der erfolgreichsten Anwendungen<br />

formaler Techniken.<br />

Definition(Typsystem):<br />

Das Typsystem einer Sprache S beschreibt,<br />

• welche Typen es in S gibt,<br />

• wie Programme von S typisiert werden,<br />

• welche Bedingungen typisierte Programme erfüllen müssen<br />

(Typisierungsbedingungen).<br />

Ein Programm, das die Typisierungsbedingungen erfüllt,<br />

heißt typkorrekt.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 208<br />

Definition(Typfehler):<br />

Ein Typfehler tritt auf, wenn<br />

• einer Variablen ein Wert von einem falschen Typ<br />

zugewiesen wird;<br />

• eine Operation mit aktuellen Parametern aufgerufen wird,<br />

für die sie nicht definiert ist.<br />

Ein Typisierungsfehler tritt auf, wenn ein Programm nicht<br />

typkorrekt ist.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 209<br />

Definition(typsicher):<br />

Eine Sprache heißt typsicher (engl. type-safe), wenn bei<br />

Ausführung ihrer (typkorrekten) Programme keine Typfehler<br />

auftreten.<br />

Ein Typsystem heißt sicher (engl. sound), wenn es<br />

Typsicherheit garantiert.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 210<br />

Bemerkung:<br />

• Es gibt Programme, die nicht typkorrekt sind, aber<br />

trotzdem nicht zu Typfehlern führen.<br />

• Bei einem sicheren Typsystem folgt Typsicherheit also aus<br />

Typkorrektheit.<br />

Literatur zur Typisierung:<br />

Kim B. Bruce: Foundations of Object-Oriented Languages.<br />

Types and Semantics. MIT Press, 2002.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 211<br />

3.1.1 Typinformation und ihre statische und<br />

dynamische Prüfung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 212<br />

Bei Objekten liefert der Typ insbesondere die Information,<br />

welche Nachrichten ein Objekt versteht. Damit kann in<br />

einem typkorrekten Programm gewährleistet werden, dass zu<br />

jedem Methodenaufruf eine Methodenimplementierung<br />

existiert.<br />

Ziele der Typisierung in der OO-Programmierung:<br />

• Vermeidung von Typfehlern<br />

• Optimierung<br />

• Dokumentation<br />

• Abstraktion<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 213<br />

Definition(Typprüfung):<br />

Die Typprüfung besteht aus der (statischen) Prüfung der<br />

Typisierungsbedingungen und der Prüfung von<br />

Typeigenschaften zur Laufzeit (dynamische Typprüfung).<br />

Eine typsichere Sprache heißt statisch typisiert, wenn sie<br />

keine dynamische Typprüfung vorsieht.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 214<br />

Beispiel(statisch typisiert):<br />

Java ist nicht statisch typisiert, sondern verlangt dynamische<br />

Typprüfung bei:<br />

• der Typkonvertierung (casts):<br />

Object obj = "Ich neues String-Objekt";<br />

String str = (String) obj;<br />

...<br />

• Feldzugriffen:<br />

String[] strfeld = new String[2];<br />

Object[] objfeld = strfeld;<br />

objfeld[0] = new Object();<br />

int strl = strfeld[0].length();<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 215<br />

Typisierungsproblematik in OO-Sprachen<br />

Damit ein Subtyp-Objekt an allen Stellen vorkommen kann,<br />

an denen ein Supertyp-Objekt erwartet wird, muss garantiert<br />

sein, dass<br />

• ein Subtyp-Objekt alle Attribute seiner Supertypen hat;<br />

• ein Subtyp-Objekt alle Methoden der Supertypen hat;<br />

• die Attribute und Methoden im Subtyp zu denen in den<br />

Supertypen typmäßig passen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 216<br />

Definition(Ko-/Kontravarianz):<br />

Sei S ein Subtyp von T.<br />

Sei TV ein Typvorkommen in T (Attribut-, Parameter-,<br />

Ergebnistyp) und SV das entsprechende Typvorkommen in S.<br />

Wir sagen:<br />

• SV und TV sind kovariant, wenn SV ein Subtyp von TV<br />

ist.<br />

• SV und TV sind kontravariant, wenn TV ein Subtyp von<br />

SV ist.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 217<br />

Fakt:<br />

OO-Sprachen lassen sich nur dann statisch typisieren, wenn:<br />

• Attributtypen ko- und kontravariant, d.h. invariant sind.<br />

• Parametertypen kontravariant sind.<br />

• Ergebnistypen kovariant sind.<br />

Beispiel(Ko-/Kontravarianz):<br />

interface C1 { String a; ... }<br />

class D1 implements C1 { Object a; ... }<br />

...<br />

C1 cvar = new D1(); // initialisiert a<br />

String svar = cvar.a;<br />

// Typfehler: Kovarianz nicht gegeben<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 218<br />

interface C2 { Object a; ... }<br />

class D2 implements C2 { String a; ... }<br />

...<br />

C2 cvar = new D2();<br />

cvar.a = new Object();<br />

// Typfehler: Kontravarianz nicht gegeben<br />

interface C3 { String m(); ... }<br />

class D3 implements C3 { Object m(){...} ...}<br />

...<br />

C3 cvar = new D3();<br />

String svar = cvar.m();<br />

// Typfehler: Kovarianz nicht gegeben<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 219<br />

interface C4 { int m(Object p); ... }<br />

class D4 implements C4 {<br />

int m(String s){<br />

s.length();...<br />

}<br />

...<br />

}<br />

...<br />

C4 cvar = new D4();<br />

cvar.m( new Object() );<br />

// Typfehler bei Ausfuehrung von m:<br />

// Kontravarianz nicht gegeben<br />

Entsprechendes gilt für die Typen der erlaubten Ausnahmen<br />

einer Methode.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 220<br />

Bemerkung:<br />

• Die Ko- und Kontravarianz sind grundlegend für das<br />

Verständnis von Typsystemen und konformer<br />

Subtypbildung in OO-Sprachen.<br />

• Java bietet ein recht inflexibles Typsystem:<br />

◦ keine echt kontravarianten Parametertypen<br />

◦ keine echt kovarianten Ergebnistypen<br />

◦ Kovarianz nur bei den erlaubten Ausnahmen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 221<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

3.1.2 Typsicherheit


3.1 Einführung 222<br />

Wir diskutieren Typsicherheit am Beispiel von Java-KE.<br />

Typsystem von Java-KE:<br />

• Typen: boolean, int, Null und ein Typ für jede deklarierte<br />

Klasse und Schnittstelle.<br />

• Subtypbeziehung wie in Java:<br />

◦ Alle Referenztypen sind Subtyp von Object<br />

◦ Jede Typdeklaration für T legt die direkten Supertypen von T fest.<br />

◦ Null ist Subtyp aller Referenztypen<br />

◦ keine Subtypbeziehung zwischen Basisdatentypen und zwischen<br />

Basisdaten- und Referenztypen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 223<br />

• Typisierung von Java-KE:<br />

◦ Deklarationen sind typisiert;<br />

◦ Ausdrücke gemäß Signatur der Operatoren, der Variablendeklaration<br />

bzw. Konstanten (null bekommt den Typ Null);<br />

◦ Anweisungsteile gemäß den Deklarationen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 224<br />

• Typisierungsbedingungen von Java-KE:<br />

◦ Eine überschreibende Methode hat die gleichen Parameter- und<br />

Ergebnistypen wie die überschriebene Methode.<br />

◦ Ausdrücke in if- und while-Anweisungen müssen vom Typ boolean sein<br />

◦ Der Zieltyp C bei einer Typkonvertierung, x=(C) e, muss ein Subtyp<br />

vom Typ von e sein.<br />

◦ Der Typ der linken Seite einer Zuweisung, x = e, muss ein Supertyp<br />

vom Typ von e sein.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 225<br />

Lemma:<br />

Das Typsystem von Java-KE ist sicher. Für jede Anweisung<br />

pp und Zustände S, SQ gilt:<br />

wt(S, pp) ∧ ssem(S, pp, SQ) ⇒ wt(SQ, pp)<br />

wobei wt wie auf Folie 129 definiert ist.<br />

Beweisskizze:<br />

Seien S und pp beliebig. Der syntaktischen Interpretation<br />

der SOS von Java-KE zu Folge, gibt es einen Herleitungsbaum<br />

HQ von endlicher Tiefe für ssem(S, pp, SQ).<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 226<br />

Induktion nach der Herleitungstiefe n von HQ:<br />

Induktionsanfang n=1:<br />

Fallunterscheidung über die nicht-rekursiven Regeln. Wir<br />

betrachten hier exemplarisch die 1. Regel für die Zuweisung<br />

mit Typkonvertierung. Z.z.:<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 227<br />

wt(S[x := e[S]], pp) mit pp = (x = (T )e)<br />

⇔ // wg. Definition von wt<br />

S[x := e[S]](this) = null ∧ wts(S[x := e[S]]($))<br />

∧ ∀VarId V : V ∈ vis(pp)<br />

⇒ typ(S[x := e[S]](V )) styp(V , pp)<br />

⇐ // wg. x = this<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 228<br />

⇐ // wg. x = this<br />

S(this) = null ∧ wts(S($)) ∧ typ(e[S]) styp(x, pp)∧<br />

∀ VarId V : V ∈ vis(pp) ⇒ typ(S(V )) styp(V , pp)<br />

⇐ // wg. typ(e[S]) T aus Antecedent der Regel,<br />

// und T styp(x, pp) aus Typisierungsbedingungen<br />

wt(S, pp)<br />

Entsprechend müssen alle anderen nicht-rekursiven<br />

Inferenzregeln untersucht werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 229<br />

Induktionsschritt n→n+1:<br />

Fallunterscheidung über die Regeln mit ssem im Antecedent.<br />

Wir betrachten hier exemplarisch die Regel für if-then-else<br />

und nehmen e[S] an. Z.z.:<br />

wt(SQ, pp) mit pp = if (e){s1 }else{s2 }<br />

⇔ // wg. Definition von wt<br />

wt(SQ, s1 )<br />

Und das folgt wegen ssem(S, s1 , SQ) und wt(S, s1 ) aus der<br />

Induktionsvoraussetzung. Entsprechend müssen alle anderen<br />

rekursiven Inferenzregeln untersucht werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.1 Einführung 230<br />

Literatur zu Typsicherheit von OO-Sprachen:<br />

S. Drossopoulou, S. Eisenbach: Java is Type Safe — Probably.<br />

European Conference on Object-Oriented<br />

Programming, 1997 (LNCS 1241).<br />

T. Nipkow, D. v. Oheimb: Java light is Type-Safe — Definitely.<br />

Principles of Programming Languages, 1998.<br />

A. Igarashi, B. Pierce, P. Wadler:<br />

Featherweight Java: A Minimal Core Calculus for Java and GJ<br />

Object-Oriented Programming, Systems, Languages, and Applications,<br />

1999.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 231<br />

3.2 Parametrische Typsysteme und virtuelle<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

Klassen


3.2 Parametrische Typsysteme und virtuelle Klassen 232<br />

Reine Subtyp-Polymorphie bietet bei bestimmten wichtigen<br />

Anwendungssituationen keine ausreichende Unterstützung:<br />

• Parametrisierung von Typen<br />

• Spezialisieren verwendeter Typen in Subklassen<br />

Dieser Abschnitt erläutert Lösungen für diese Probleme.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 233<br />

3.2.1 Parametrische Typsysteme<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 234<br />

Parametrisierung von Softwarekomponenten ist ein<br />

entscheidender Weg zur Wiederverwendung.<br />

Subtyp-Polymorphie leistet dazu eine wichtigen Beitrag.<br />

Nachteile:<br />

• Spezialisierung nur entlang der Subtyp-Ordnung<br />

• Keine Parametrisierung bzgl. verwendeter Typen<br />

• Keine Einschränkung der Polymorphie<br />

Moderne OO-Sprachen kombinieren Subtyp- und<br />

parametrische Polymorphie.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 235<br />

Wir betrachten hier GJ als Beispiel einer OO-Sprache mit<br />

parametrischem Polymorphismus.<br />

Literatur:<br />

G. Bracha, M. Odersky, D. Stoutamire, P. Wadler:<br />

Making the future safe for the past: Adding Genericity to<br />

the Java Programming Language.<br />

Object-Oriented Programming, Systems, Languages, and<br />

Applications, 1998.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 236<br />

Parametrische/generische Typen<br />

Idee: Erlaube an Anwendungsstellen von Typen Typvariablen<br />

anstelle von Typen.<br />

Dadurch ergeben sich parametrisierte Klassen- und<br />

Schnittstellendeklarationen. Die Typvariablen müssen beim<br />

deklarierten Typ vereinbart werden.<br />

Beispiel(Typvariablen):<br />

class Pair {<br />

A fst;<br />

B snd;<br />

Pair(A f,B s){ ... }<br />

...<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 237<br />

Pair〈A,B〉 heißt ein parametrisierter Typ.<br />

Pair heißt Typkonstruktor.<br />

Typparameter werden bei der Objekterzeugung instanziert:<br />

Pair paarvar =<br />

new Pair (<br />

new String(), new Integer() );<br />

Ein Typ wird in GJ dargestellt durch:<br />

• einen (parameterloser) Typbezeichner,<br />

• eine Typvariable,<br />

• einen Typkonstruktor angewandt auf Typen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 238<br />

Beispiele:<br />

• String<br />

• A, wobei A eine deklarierte Typvariable ist.<br />

• Pair〈String, Object〉<br />

• Pair〈Pair〈A,A〉, String〉<br />

Wichtigste Anwendung parametrisierter Typen sind<br />

Kollektionstypen und frei erzeugte Typen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 239<br />

interface Collection {<br />

public void add (A x);<br />

public Iterator iterator ();<br />

}<br />

interface Iterator {<br />

public A next ();<br />

public boolean hasNext ();<br />

}<br />

class NoSuchElementException extends RuntimeException {}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 240<br />

class LinkedList implements Collection {<br />

protected class Node {<br />

A elt;<br />

Node next = null;<br />

Node (A elt) { this.elt = elt; }<br />

}<br />

protected Node head = null, tail = null;<br />

public LinkedList () {}<br />

public void add (A elt) {<br />

if (head == null) {<br />

head = new Node(elt);<br />

tail = head;<br />

} else {<br />

tail.next = new Node(elt);<br />

tail = tail.next;<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


}<br />

3.2 Parametrische Typsysteme und virtuelle Klassen 241<br />

public Iterator iterator () {<br />

return new Iterator () {<br />

protected Node ptr = head;<br />

public boolean hasNext () {<br />

return ptr != null;<br />

}<br />

public A next () {<br />

if (ptr != null) {<br />

A elt = ptr.elt;<br />

ptr = ptr.next;<br />

return elt;<br />

} else {<br />

throw new<br />

NoSuchElementException ();<br />

}<br />

}<br />

};<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 242<br />

class Test {<br />

public static void main (String[] a) {<br />

LinkedList ys = new LinkedList();<br />

ys.add("zero");<br />

ys.add("one");<br />

String y = ys.iterator().next();<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 243<br />

Parametrische/generische Methoden<br />

Analog zu Typdeklarationen lassen sich auch<br />

Methodendeklarationen parametrisieren.<br />

Beispiel(Parametrische Methoden):<br />

interface SomeCollection extends Collection {<br />

public A some();<br />

}<br />

class Collections {<br />

public static <br />

Pair somepair(SomeCollection xa,<br />

SomeCollection xb ) {<br />

return new Pair(xa.some(),xb.some());<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 244<br />

Einschränkung von Typvariablen<br />

Manchmal möchte man die Instanzierung von Typvariablen<br />

auf bestimmte Typen einschränken. In GJ lassen sich solche<br />

Einschränkungen (engl. bounds) bei der Deklaration der<br />

Typvariablen angeben:<br />

〈A implements T〉<br />

〈B extends T〉<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 245<br />

Beispiel(Einschränkung von Typvariablen):<br />

interface Comparable {<br />

public int compareTo (A that);<br />

}<br />

class Byte implements Comparable {<br />

private byte value;<br />

public Byte (byte value) {<br />

this.value = value;<br />

}<br />

public byte byteValue () { return value; }<br />

public int compareTo (Byte that) {<br />

return this.value - that.value;<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 246<br />

class Collections {<br />

public static <br />

A max (Collection xs) {<br />

Iterator xi = xs.iterator();<br />

A w = xi.next();<br />

while (xi.hasNext()) {<br />

A x = xi.next();<br />

if (w.compareTo(x) < 0) w = x;<br />

}<br />

return w;<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 247<br />

Bemerkung:<br />

• Trotz der relativ einfachen Erweiterung des Typsystems<br />

ergeben sich bereits recht umfangreiche Typisierungsregeln.<br />

• Generische Typen und Methoden sind kanonische Beispiele<br />

für parametrische Softwarekomponenten.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 248<br />

Subtyping zwischen parametrischen Typen<br />

Auch für parametrische Typen gilt:<br />

Ein Typ ist nur dann ein Subtyp eines anderen, wenn die<br />

Subtypbeziehung explizit aus den Deklarationen oder<br />

Einschränkungen ersichtlich ist:<br />

LinkedList implements Collection<br />

SomeCollection extends Collection<br />

Byte implements Comparable<br />

<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 249<br />

Die Subtypbeziehung zwischen Typparametern überträgt sich<br />

nicht auf parametrische Typen:<br />

LinkedList LinkedList<br />

Es wird Invarianz bei den Parametern verlangt.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 250<br />

Beispiel(Subtypbeziehung):<br />

Folgendes Beispiel zeigt, warum Gleichheit bei aktuellen<br />

Typparametern verlangt wird:<br />

class Loophole {<br />

public static String loophole (Byte y) {<br />

LinkedList xs = new LinkedList();<br />

LinkedList ys = xs;<br />

// Uebersetzungsfehler<br />

ys.add(y);<br />

return xs.iterator().next();<br />

}<br />

}<br />

Anders als bei Feldern ist der Typ des Parameters zur<br />

Laufzeit nicht verfügbar. Deshalb ist eine dynamische<br />

Prüfung wie bei Feldern nicht möglich.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 251<br />

Typinferenz<br />

GJ benutzt einen Typinferenzalgorithmus, der<br />

• lokal ist, d.h. der Typ eines Ausdrucks ergibt sich nur aus<br />

den Typen der Teilausdrücke;<br />

• Ausdrücke von beliebigem Referenztyp bewältigen kann<br />

(null, leere Listen);<br />

• Subsumption beherrscht, d.h. der Typ T eines Ausdrucks<br />

kann zu jedem beliebigen Supertyp verallgemeinert werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 252<br />

Beispiel(Typinferenz):<br />

class ListFactory {<br />

public LinkedList empty () {<br />

return new LinkedList();<br />

}<br />

public LinkedList singleton (A x) {<br />

LinkedList xs = new LinkedList();<br />

xs.add(x);<br />

return xs;<br />

}<br />

public LinkedList doublet (A x, A y) {<br />

LinkedList xs = new LinkedList();<br />

xs.add(x);<br />

xs.add(y);<br />

return xs;<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 253<br />

class Test {<br />

static ListFactory f = new ListFactory();<br />

public static void main (String[ ] args) {<br />

LinkedList zs = f.doublet(new Integer(1), new Float(1.0));<br />

LinkedList ys = f.singleton(null);<br />

LinkedList xs = f.empty();<br />

LinkedList err = f.doublet("abc", new Integer(1));<br />

// compile-time error<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 254<br />

Lösungsidee:<br />

Erweitere die Typausdrücke um den Typ ’*’, der Subtyp aller<br />

Referenztypen ist. Für ’*’ wird kovariantes Subtyping auf<br />

Parameterposition akzeptiert, d.h. z.B.:<br />

LinkedList ist Subtyp von LinkedList<br />

Pair ist Subtyp von Pair<br />

Für Typsicherheit ist folgende Linearitätseinschränkung<br />

erforderlich:<br />

Eine Typvariable, die mehrfach als Ergebnistyp einer<br />

Methode vorkommt, darf nicht durch ’*’ instanziert werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 255<br />

Beispiel(Typinferenz):<br />

class Cell {<br />

public A value;<br />

public Cell (A v) { value = v; }<br />

public static Cell make (A x) {<br />

return new Cell(x);<br />

}<br />

}<br />

class Pair {<br />

public B fst;<br />

public C snd;<br />

public Pair (B x, C y) { fst = x; snd = y; }<br />

public static Pair duplicate (D x) {<br />

return new Pair(x,x);<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 256<br />

class Loophole {<br />

public static String loophole (Byte y) {<br />

Pair p =<br />

Pair.duplicate(Cell.make(null));<br />

// compile-time error<br />

p.snd.value = y;<br />

return p.fst.value;<br />

}<br />

public static String permitted (String x) {<br />

Pair p =<br />

Pair.duplicate(Cell.make((String)null));<br />

p.fst.value = x;<br />

return p.snd.value;<br />

}<br />

}<br />

Nach Inferenz der Typen ist die Typprüfung einfach.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 257<br />

Realisierung von Generic Java<br />

Im Wesentlichen läßt sich GJ direkt nach Java übersetzen.<br />

Die Implementierung parametrischer Typen basiert auf:<br />

• Parameterlöschung:<br />

◦ Löschen der Typparameter<br />

◦ Verwenden von Object anstelle von Typvariablen<br />

◦ Einsetzen geeigneter Typkonvertierungen (casts)<br />

• Brückenmethoden<br />

◦ Wenn eine Subklasse eine Typvariable einer Superklasse instanziert,<br />

sind ggf. zusätzliche Methoden mit geeigneter Signatur<br />

hinzuzufügen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 258<br />

Beispiel(Parameterlöschung und Brückenmethoden):<br />

Durch Parameterlöschung und Einführen von<br />

Brückenmethoden erhält man zu obigem Beispiel:<br />

interface Comparable {<br />

public int compareTo (Object that);<br />

}<br />

class Byte implements Comparable {<br />

private byte value;<br />

public Byte (byte value) { this.value = value; }<br />

public byte byteValue () { return value; }<br />

public int compareTo (Byte that) {<br />

return this.value - that.value;<br />

}<br />

public int compareTo (Object that) {<br />

return this.compareTo((Byte)that);<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 259<br />

class Collections {<br />

public static Comparable max (Collection xs) {<br />

Iterator xi = xs.iterator();<br />

Comparable w = (Comparable)xi.next();<br />

while (xi.hasNext()) {<br />

Comparable x = (Comparable)xi.next();<br />

if (w.compareTo(x) < 0) w = x;<br />

}<br />

return w;<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 260<br />

Probleme mit der erläuterten Technik treten auf, wenn<br />

Typparameter nur in Rückgabetypen vorkommen:<br />

class Interval implements Iterator {<br />

private int i, n;<br />

public Interval (int l, int u) { i=l; n=u; }<br />

public boolean hasNext () { return (i


3.2 Parametrische Typsysteme und virtuelle Klassen 261<br />

Parameterlöschung und Einführen von Brückenmethoden<br />

liefert:<br />

class Interval implements Iterator {<br />

private int i, n;<br />

public Interval (int l, int u) { i = l; n = u; }<br />

public boolean hasNext () { return (i


3.2 Parametrische Typsysteme und virtuelle Klassen 262<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

3.2.2 Virtuelle Typen


3.2 Parametrische Typsysteme und virtuelle Klassen 263<br />

Statt Parametrisierung von Typen kann Spezialisierung<br />

verwendet werden. Dies ergibt eine andere Art Generizität:<br />

class Vector {<br />

typedef ElemType as Object;<br />

void addElement( ElemType e ) { ... }<br />

ElemType elementAt( int index ) { ... }<br />

}<br />

class PointVector extends Vector{<br />

typedef ElemType as Point;<br />

}<br />

Man nennt ElemType hier einen virtuellen Typ. Virtuelle<br />

Typen können in Subklassen mit Subtypen überschrieben<br />

werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 264<br />

Im Folgenden betrachten wir eine Erweiterung von Java um<br />

virtuelle Typen.<br />

Literatur:<br />

Kresten Krab Thorup:<br />

Genericity in Java with Virtual Types.<br />

European Conference on Object-Oriented Programming,<br />

1997.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 265<br />

Aspekte virtueller Typen<br />

1. Unterscheidung zwischen parametrischen Typen und<br />

,,normalen“ Typen ist nicht nötig:<br />

interface IteratorOfObject {<br />

typedef A as Object;<br />

public A next ();<br />

public boolean hasNext ();<br />

}<br />

interface CollectionOfObject {<br />

typedef A as Object;<br />

typedef IteratorOfA as IteratorOfObject;<br />

public void add (A x);<br />

public IteratorOfA iterator ();<br />

}<br />

class NoSuchElementException extends RuntimeException {}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 266<br />

class LinkedListOfObject implements CollectionOfObject {<br />

// erbt die virtuellen Typen A und IteratorOfA<br />

protected class Node {<br />

A elt;<br />

Node next = null;<br />

Node (A elt) { this.elt = elt; }<br />

}<br />

protected Node head = null, tail = null;<br />

}<br />

public LinkedListOfObject () {}<br />

public void add (A elt) { ... /* wie auf Folie 240 */ }<br />

public IteratorOfA iterator () {<br />

return new IteratorOfA () {... /* wie auf Folie 241 */ };<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 267<br />

interface IteratorOfString extends IteratorOfObject {<br />

typedef A as String;<br />

}<br />

class LinkedListOfString extends LinkedListOfObject {<br />

typedef A as String;<br />

typedef IteratorOfA as IteratorOfString;<br />

}<br />

class Test {<br />

public static void main (String[] a) {<br />

LinkedListOfString ys = new LinkedListOfString();<br />

ys.add("zero");<br />

ys.add("one");<br />

String y = ys.iterator().next();<br />

}<br />

}<br />

Jede Instanzierung benötigt eigene Typdeklaration.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 268<br />

2. Subtypbeziehungen zwischen generischen Typen können<br />

deklariert werden:<br />

LinkedListOfString ist Subtyp von<br />

LinkedListOfObject; also ist folgendes Fragment<br />

typkorrekt:<br />

LinkedListOfString strl = new LinkedListOfString();<br />

LinkedListOfObject objl = strl;<br />

objl.add( new Object() ); // VirtualTypeCastException<br />

Die durch virtuelle Typen entstehende Kovarianz bei<br />

Methodenparametern wird durch dynamische Typprüfung<br />

abgefangen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 269<br />

3. Rekursive Typen und Zusammenhang mit Vererbung<br />

lassen sich besser realisieren.<br />

a) Verschränkte Rekursion am Beispiel des<br />

Observer-Musters:<br />

interface Observer {<br />

typedef SType as Subject;<br />

typedef EventType as Object;<br />

void notify (SType subj, EventType e);<br />

}<br />

class Subject {<br />

typedef OType as Observer;<br />

typedef EventType as Object;<br />

OType observers[];<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


}<br />

3.2 Parametrische Typsysteme und virtuelle Klassen 270<br />

notifyObservers (EventType e) {<br />

int len = observers.length;<br />

for (int i=0; i


3.2 Parametrische Typsysteme und virtuelle Klassen 271<br />

b) Rekursives Vorkommen des deklarierten Typs:<br />

Der deklarierte Typ K kann im Rumpf seiner Deklaration mit<br />

,,This“ bezeichnet werden. Dann werden in einer Subklasse<br />

SUBK alle diese Vorkommen als Vorkommen von SUBK<br />

interpretiert und entsprechend in weiteren Subtypen:<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 272<br />

class SLinkedList {<br />

This tail;<br />

public This getTail() { return tail; }<br />

}<br />

class SLinkedListOfObject extends SLinkedList {<br />

typedef Elem as Object;<br />

Elem head;<br />

public Elem getHead() { return head; }<br />

}<br />

class SLinkedListOfString extends SLinkedListObject {<br />

typedef Elem as String;<br />

// SLinkedListOfString.getTail liefert SLinkedListOfString<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 273<br />

Diskussion virtueller Typen<br />

• Vorteile:<br />

◦ keine neue Beziehung zwischen Typen (nur ,,ist Subtyp von“, nicht<br />

,,ist Typinstanz von“)<br />

◦ Subtypbeziehung zwischen ,,parametrischem“ und ,,instanziertem“<br />

Typ möglich<br />

◦ Rekursive Abhängigkeiten lassen sich flexibler behandeln<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 274<br />

• Nachteile:<br />

◦ Zusätzliche dynamische Typprüfung sind nötig (vor allem wegen<br />

kovarianten Methodenparametern):<br />

⊲ Verlust an statischer Typprüfbarkeit<br />

⊲ Verlust an Effizienz<br />

◦ rekursive Instanzierung (Beispiel Byte, Folie 245 ) nicht unterstützt.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 275<br />

• Anmerkungen:<br />

◦ Der Vorschlag von Thorup erlaubt es, virtuelle Typen als Subtypen<br />

mehrerer Typen zu deklarieren und dabei einen Klassentypen für die<br />

Erzeugung von Objekten auszuzeichnen.<br />

◦ Es gibt mittlerweile mehrere Arbeiten, die eine Integration von<br />

parametrischen und virtuellen Typen vorschlagen, z.B.:<br />

K. Bruce, M. Odersky, P. Wadler:<br />

A statically safe alternative to virtual types.<br />

European Conference on Object-Oriented Programming, 1998.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 276<br />

Realisierung virtueller Typen<br />

Typsicherheit wird in der Realisierung der vorgestellten<br />

Variante durch Einführen dynamischer Prüfungen erzielt.<br />

Wir unterscheiden primäre und überschreibende<br />

Deklarationen virtueller Typen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 277<br />

Wesentliche Ideen:<br />

• Benutze für die Umsetzung eines virtuellen Typs T den<br />

Typ aus der primären Deklaration von T.<br />

• Definiere für jede primäre Deklaration eines virtuellen<br />

Typen T eine Cast-Methode. Diese Cast-Methode wird in<br />

Subtypen mit überschreibenden Deklarationen für T<br />

überschrieben.<br />

• Benutze die Cast-Methode zur Prüfung aktueller Parameter.<br />

• Um Typkorrektheit in den resultierenden Java-Programmen<br />

zu erreichen, füge weitere Typkonvertierungen ein (Casts).<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 278<br />

Beispiel(Realisierung virtueller Typen):<br />

class Vector {<br />

typedef ElemType as Object;<br />

void addElement( ElemType e ) { ... }<br />

...<br />

}<br />

class PointVector extends Vector {<br />

typedef ElemType as Point;<br />

void addElement( ElemType e ) {<br />

...<br />

e.getX()<br />

...<br />

}<br />

}<br />

PointVector pv;<br />

Point pnt;<br />

...<br />

pv.addElement(pnt);<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 279<br />

wird umgesetzt in<br />

class Vector {<br />

Object cast$T(Object o) { return o; }<br />

void check$addElement( Object o ) {<br />

this.addElement( this.cast$T(o) );<br />

}<br />

void addElement( Object e ) { ... }<br />

...<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.2 Parametrische Typsysteme und virtuelle Klassen 280<br />

class PointVector extends Vector {<br />

Object cast$T(Object o) {<br />

try {<br />

return (Point)o;<br />

} catch( ClassCastException c ) {<br />

throw new VirtualTypeCastException (...);<br />

}<br />

}<br />

void addElement( Object e$0 ) {<br />

Point e = (Point)e$0;<br />

...<br />

e.getX()<br />

...<br />

}<br />

}<br />

PointVector pv;<br />

Point pnt;<br />

...<br />

pv.check$addElement(pnt);<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 281<br />

3.3 Typsysteme zur Strukturierung von<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

Objektgeflechten


3.3 Typsysteme zur Strukturierung von Objektgeflechten 282<br />

Typisierungstechniken kann man nicht nur zur Vermeidung<br />

(klassischer) Typfehlern nutzen, sondern auch zur<br />

Sicherstellung anderer Invarianten.<br />

Wir betrachten hier die Sicherstellung von Kapselungseigenschaften<br />

(vgl. 2.4.2 ):<br />

3.3.1 Kapselung auf Paketebene: Confined Types<br />

3.3.2 Andere Strukturierungsanätze<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 283<br />

3.3.1 Kapselung auf Paketebene: Confined Types<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 284<br />

Ziel:<br />

Garantiere, dass Objekte bestimmter Typen nur vom<br />

Programmcode eines Packages manipuliert werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 285<br />

Grundideen:<br />

1. Betrachte jedes Paket P als Kapsel; d.h. alle Objekte (der<br />

Klassen) von P liegen in der gleichen Kapsel. Kapseln sind<br />

also disjunkt.<br />

2. Markiere Typen, deren Objekte gekapselt werden sollen,<br />

als ,,confined“. Die Objekte dieser Typen nennen wir<br />

gekapselt.<br />

3. Lege Regeln fest, die garantieren, dass Referenzen auf<br />

gekapselte Objekte eines Pakets P nur in Instanzvariablen,<br />

Parametern und lokalen Variablen von Objekten von P<br />

gehalten werden können.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 286<br />

outside<br />

ungekapselt<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

ungekapselt<br />

inside<br />

gekapselt


3.3 Typsysteme zur Strukturierung von Objektgeflechten 287<br />

Zusammenhang zu Typsystemen<br />

• Jede Variable bekommt als erweiterte Typinformation:<br />

◦ das Paket, zu dem sie gehört (implizit)<br />

• Jedes Objekt bekommt als erweiterte Typinformation:<br />

◦ das Paket, zu dem es gehört (implizit)<br />

◦ die Information, ob gekapselt oder nicht<br />

• Kapselungsverletzung (Typfehler) passiert, wenn eine<br />

Variable von Paket P ein gekapseltes Objekt eines anderen<br />

Pakets Q referenziert.<br />

• Es gibt statisch prüfbare Regeln, die Kapselungsverletzungen<br />

zur Laufzeit ausschließen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 288<br />

Im Folgenden betrachten wir eine Erweiterung von Java um<br />

gekapselte Typen im obigen Sinne.<br />

Literatur:<br />

B. Bokowski, J. Vitek:<br />

Confined Types.<br />

OOPSLA, 1999.<br />

Bemerkung:<br />

Das Studium der Kapselungsregelungen ist auch für die<br />

Entwicklung von OO-Programmen im Allg. hilfreich.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 289<br />

Szenarien für Export von Referenzen<br />

package inside;<br />

public class C extends outside.B {<br />

void putReferences() {<br />

C c = new C();<br />

/*r1*/ outside.B.c1 = c;<br />

/*r2*/ outside.B.storeReference(c);<br />

/*r3*/ outside.B.c3s = new C[] {c};<br />

/*r4*/ calledByConfined();<br />

/*r5*/ implementedInSubclass();<br />

/*r6*/ throw new E();<br />

}<br />

void implementedInSubclass() { }<br />

/*r7*/ static C f = new C();<br />

/*r8*/ static C m() {<br />

return new C();<br />

}<br />

/*r9*/ static C[] fs = new C[]{new C()};<br />

/*r10*/ public C() { } }<br />

public class E extends RuntimeException { }<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 290<br />

Szenarien für Import von Referenzen<br />

package outside;<br />

public class B {<br />

/*r1*/ static inside.C c1;<br />

/*r2*/ static void storeReference(inside.C c2) { // store c2 }<br />

/*r3*/ static inside.C[] c3s;<br />

/*r4*/ void calledByConfined() { // store this }<br />

static void getReferences() {<br />

/*r7*/ inside.C c7 = inside.C.;<br />

/*r8*/ inside.C c8 = inside.C.m();<br />

/*r9*/ inside.C[] c9s = inside.C.fs;<br />

/*r10*/ inside.C c10 = new inside.C();<br />

D d = new D();<br />

try { d.putReferences();<br />

/*r6*/ } catch (inside.E ex) { // store ex }<br />

}<br />

}<br />

class D extends inside.C {<br />

/*r5*/ void implementedInSubclass() { // store this }<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 291<br />

Statische Kapselungsregeln<br />

Folgende Regeln garantieren die Kapselungsinvariante (dabei<br />

müssen Felder mit gekapseltem Elementtyp wie gekapselte<br />

Typen behandelt werden):<br />

C1: Gekapselte Typen dürfen weder public noch protected<br />

sein und nicht zum unbenannten globalen Paket gehören.<br />

C2: Subtypen von gekapselten Typen müssen auch gekapselt<br />

sein und zum gleichen Paket wie ihr Supertyp gehören.<br />

C3: Typerweiterung von gekapselten zu ungekapselten Typen<br />

ist unzulässig in Zuweisungen, Methodenaufrufen,<br />

Rückgabeanweisungen und Casts.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 292<br />

Die folgenden beiden Regeln benutzen den Begriff ,,anonyme<br />

Methode“ bzw. ,,anonyme Konstruktoren“, den wir weiter<br />

unten erläutern:<br />

C4: Methoden, die auf gekapselten Objekten aufgerufen<br />

werden, müssen entweder in gekapselten Klassen deklariert<br />

oder anonyme Methoden sein.<br />

C5: Konstruktoren, die von Konstruktoren gekapselten<br />

Klassen aufgerufen werden, müssen entweder in gekapselten<br />

Klassen deklariert oder anonyme Methoden sein.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 293<br />

C6: Subtypen von java.lang.Throwable und java.lang.Thread<br />

dürfen nicht als gekapselt deklariert werden.<br />

C7: Der Typ von öffentlichen und geschützten Attributen<br />

darf nicht gekapselt sein.<br />

C8: Der Ergebnistyp von öffentlichen und geschützten<br />

Methoden darf nicht gekapselt sein.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 294<br />

Definition(Anonyme Menge von Methoden):<br />

Eine Menge von Methoden kann als anonym deklariert<br />

werden, wenn sie die folgenden Bedingungen erfüllt:<br />

A1: Der implizite Parameter this wird nur benutzt, um auf<br />

Instanzvariablen zuzugreifen oder anonyme Methoden auf<br />

dem aktuellen Objekt aufzurufen.<br />

A2: Anonyme Methoden dürfen nur durch anonyme<br />

Methoden überschrieben werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 295<br />

A3: Native Methoden dürfen nicht anonym sein.<br />

Eine Menge von Konstruktoren kann als anonym deklariert<br />

werden, wenn jeder Konstruktor der Menge nur anonyme<br />

Konstruktoren aufruft.<br />

Bemerkung:<br />

• Das Verhalten anonymer Methoden wird nur von den<br />

aktuellen Parametern und den Werten der Instanzvariablen<br />

bestimmt.<br />

• Anonyme Methoden führen nicht zu neuen Aliasen für<br />

ihren impliziten Parameter.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 296<br />

3.3.2 Andere Strukturierungsansätze<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 297<br />

In der Literatur werden weitere Strukturierungsansätze<br />

diskutiert. Wir betrachten hier:<br />

• Ballontypen:<br />

◦ P. S. Almeida: Balloon Types: Controlling Sharing of State in Data<br />

Types. ECOOP ’97.<br />

• Besitzrelation:<br />

◦ D. G. Clarke, J. M. Potter, J. Noble: Ownership Types for Flexible<br />

Alias Protection. OOPSLA ’98.<br />

◦ Simple Ownership Types for Object Containment. ECOOP ’01.<br />

◦ P. Müller, A. Poetzsch-Heffter: A Type System for Controlling Representation<br />

Exposure in Java. Formal Techniques for Java Programs ’00.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 298<br />

Verwandte Themen sind:<br />

• Vermeidung von Aliasing<br />

• Realisierung von Schreibschutz<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 299<br />

Ballontypen<br />

Ein Typ kann als Ballontyp markiert werden.<br />

Objekte von Ballontypen heißen Ballonobjekte.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 300<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 301<br />

Definition(Cluster):<br />

Sei G der Graph mit Objekten als Knoten und mit den<br />

Referenzen zwischen Nicht-Ballonobjekten und von<br />

Ballonobjekten zu Nicht-Ballonobjekten als Kanten. Ein<br />

Cluster ist ein maximaler zusammenhängender Untergraph<br />

von G.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 302<br />

Definition(Interne Objekte):<br />

Ein Objekt O ist intern zu einem Ballonobjekt B genau<br />

dann, wenn gilt:<br />

• O ist ein Nicht-Ballonobjekt im gleichen Cluster wie B, oder<br />

• O ist ein Ballonobjekt, das von B oder einem Objekt im<br />

gleichen Cluster wie B referenziert wird, oder<br />

• es gibt ein zu B internes Ballonobjekt B’, zu dem O intern<br />

ist.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 303<br />

Definition(Externe Objekte):<br />

Ein Objekt O ist extern zu einem Ballonobjekt B genau<br />

dann, wenn es ungleich B ist und nicht intern zu B ist.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 304<br />

Balloninvariante:<br />

Für alle Ballonobjekte B gilt:<br />

• B wird von höchstens einer Instanzvariable referenziert.<br />

• Wenn es eine solche gespeicherte Referenz auf B gibt,<br />

kommt sie von einem zu B externen Objekt.<br />

• Kein internes Objekt zu B wird von einem Objekt<br />

referenziert, das extern zu B ist.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 305<br />

Bemerkung:<br />

• Die Invariante erlaubt es, dass lokale Variablen Objekte<br />

innerhalb eines Ballons referenzieren.<br />

Deshalb kann man einen Ballon auch nicht als die Menge<br />

der von einem Ballon erreichbaren Objekte definieren.<br />

• Um die Balloninvariante zu garantieren, benutzt Almeida<br />

folgende Techniken:<br />

◦ Zuweisung von Referenzen auf Ballonobjekte an Instanzvariablen ist<br />

im Allg. nicht erlaubt.<br />

◦ Datenflussanalyse<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 306<br />

Idee:<br />

Besitzrelation<br />

• Führe eine Besitzrelation zwischen Objekten ein:<br />

Objekt X gehört Objekt Y.<br />

• Benutze die Besitzrelation, um Kapselung zu realisieren:<br />

Nur der Besitzer darf auf die Objekte zugreifen, die ihm<br />

gehören.<br />

• Deklariere die Besitzrelation mittels erweiterter<br />

Typinformation.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 307<br />

Beispiel(Besitzrelation):<br />

class Engine {<br />

void start() { ... }<br />

void stop() { ... }<br />

}<br />

class Driver { ... }<br />

class Car {<br />

rep Engine engine; //Teil der Representation<br />

Driver driver; // kein Teil d.Representation<br />

Car() {<br />

engine = new rep Engine();<br />

driver = null;<br />

}<br />

rep Engine getEngine() { return engine; }<br />

void setEngine( rep Engine e){ engine=e; }<br />

void go () {<br />

if(driver!=null) engine.start();<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 308<br />

class Main {<br />

void main() {<br />

Driver bob = new Driver();<br />

// kein Besitzer<br />

Car car = new Car(); // kein Besitzer<br />

car.driver = bob;<br />

car.go();<br />

car.engine.stop(); // unzulaessig<br />

car.getEngine().stop(); // unzulaessig<br />

rep Engine e = new rep Engine();<br />

car.setEngine(e); // unzulaessig<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 309<br />

Die Besitzrelation ist eine binäre Relation zwischen<br />

Objekten. Bei der Erzeugung eines Objektes X wird<br />

festgelegt, wer Besitzer von X ist.<br />

Bei der einfachsten Variante gilt: Ein Objekt X ist<br />

• entweder global (hat also keinen Besitzer) oder<br />

• hat genau einen Besitzer.<br />

Besitzerinvariante:<br />

Alle Referenzpfade von einem globalen Objekt zu einem<br />

Objekt mit Besitzer B führen durch B.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.3 Typsysteme zur Strukturierung von Objektgeflechten 310<br />

Bemerkung:<br />

• Die Besitzerinvariante ist tendenziell allgemeiner als die<br />

Balloninvariante. Sie erlaubt Referenzen, die den Besitzbereich<br />

verlassen. Andererseits sind bei ihr temporäre<br />

Referenzen von außen in den Besitzbereich unzulässig.<br />

• In der beschriebenen Form bringt die Besitzrelation<br />

deutliche Restriktionen mit sich.<br />

• Es gibt unterschiedliche Umsetzungen und Verfeinerungen<br />

der Besitzrelation.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.4 Erweiterte statische Prüfung 311<br />

3.4 Erweiterte statische Prüfung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.4 Erweiterte statische Prüfung 312<br />

Abschnitte 3.2 und 3.3 haben Erweiterungen von<br />

Typsystemen untersucht, die die Spezifikation und Prüfung<br />

von Eigenschaften erlauben, die sich mit klassischen<br />

Typsystem nicht ausdrücken lassen.<br />

Hier betrachten wir die Prüfung von Eigenschaften, die<br />

keiner gesonderten Spezifikation bedürfen, aber von der<br />

klassischen Typprüfung nicht erfasst werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.4 Erweiterte statische Prüfung 313<br />

Beispiel(Eigenschaften für ESP):<br />

Prüfe zur Übersetzungszeit, dass folgende Fehler nicht<br />

auftreten:<br />

• Dereferenzierung der Null-Referenz.<br />

• Feldzugriff mit unzulässigem Index.<br />

Während klassische und erweiterte Typsysteme meistens<br />

entscheidbar sind, zielt die erweiterte statische Prüfung auf<br />

Eigenschaften, die<br />

• in vielen Fällen entscheidbar,<br />

• aber im Allg. unentscheidbar sind.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.4 Erweiterte statische Prüfung 314<br />

3.4.1 Allgemeine Aspekte der ESP<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.4 Erweiterte statische Prüfung 315<br />

ESP ist eine junge Technik. Grundansatz:<br />

1. Bestimme die Eigenschaften, die analysiert werden sollen.<br />

2. Annotiere Programme soweit, dass die Prüfung<br />

automatisch durchgeführt werden kann:<br />

◦ Schnittstelleninformation<br />

◦ Beweisunterstützung<br />

3. Falls die Prüfung nicht gelingt, erweitere bzw. korrigiere<br />

die Annotationen oder korrigiere das Programm und setze<br />

mit 2. fort.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.4 Erweiterte statische Prüfung 316<br />

Beispiel(Programm mit Annotationen):<br />

1. In folgendem Programm kann es zu<br />

NullPointer-Ausnahmen kommen:<br />

class Scumble {<br />

int a;<br />

int m( Scumble s ){<br />

return s.a;<br />

}<br />

}<br />

Die Methode m braucht s!= null als Vorbedingung.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.4 Erweiterte statische Prüfung 317<br />

2. In folgendem Programm kann das Prüfwerkzeug<br />

möglicherweise nicht ableiten, dass i nach der Schleife<br />

gleich 8 ist:<br />

class MyClass {<br />

int[] a;<br />

MyClass() {<br />

int i = 1;<br />

while( i


3.4 Erweiterte statische Prüfung 318<br />

3.4.2 Das Werkzeug ESC/Java<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.4 Erweiterte statische Prüfung 319<br />

In den letzten Jahren sind mehrere Werkzeuge für das<br />

erweiterte statische Prüfen entwickelt worden. Wir<br />

betrachten hier den Extended Static Checker for Java<br />

(ESC/Java).<br />

ESC/Java prüft (annotierte) Java-Programme auf<br />

• Abwesenheit von Laufzeitfehlern/Ausnahmen,<br />

• Konsistenz von Annotationen und Programm.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.4 Erweiterte statische Prüfung 320<br />

Beispiel(Konsistenz):<br />

class Consistency {<br />

static int x;<br />

//@ ensures x == 7 ;<br />

static void initX() { x = 10; }<br />

}<br />

Prüfung liefert folgendes Ergebnis:<br />

Consistency: initX() ...<br />

-------------------------------------------<br />

Consistency.java:5: Warning: Postcondition<br />

possibly not established (Post)<br />

static void initX() { x = 10; }<br />

Associated declaration is "Consistency.java",<br />

line 4, col 6:<br />

//@ ensures x == 7 ;<br />

^<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.4 Erweiterte statische Prüfung 321<br />

Technische Aspekte von ESC/Java<br />

ESC/Java basiert auf:<br />

• Spezifikationssprache JML<br />

• precondition transformation<br />

• automatischen Theorembeweisen<br />

ESC/Java ist<br />

• logisch nicht korrekt, d.h. es liefert möglicherweise<br />

unberechtigte Warnungen;<br />

• logisch nicht vollständig, d.h. es gibt Eigenschaften, die<br />

gelten, aber nicht gezeigt werden können.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


3.4 Erweiterte statische Prüfung 322<br />

Die Inkorrektheit vereinfacht das Schließen, in dem nicht alle<br />

Möglichkeiten in Betracht gezogen werden.<br />

Der verwendete automatische Theorembeweiser unterstützt<br />

die Konstruktion von Gegenbeispielen.<br />

Vorführung: (ESC/Java)<br />

Siehe Vorlesung.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4. Spezifikation<br />

objektorientierter Programme


4. Spezifikation objektorientierter Programme<br />

4.1 Spezifikation von Typen<br />

4.2 Konformität von Subtypen<br />

4.3 Module und Modularität<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

324


Zentrale Aspekte der Objektorientierung:<br />

• Information Hiding & Kapselung:<br />

◦ Wie verhält sich ein Objekt intern?<br />

◦ Wie wirkt ein Objekt auf die Umgebung?<br />

• Subtypbeziehung:<br />

◦ Wann kann ich ein Objekt anstelle eines anderen verwenden?<br />

• Zusammenfassend:<br />

◦ Was ist die Bedeutung/Semantik eines Objekts?<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

325


Beispiele:<br />

1. Beschreibung von Verhalten bei privaten Attributen:<br />

public class WieWerdeIchBeschrieben {<br />

private int a = 0;<br />

public void set( int p ) { a = p; }<br />

public int get() { return a; }<br />

}<br />

Private Klassenkomponenten sollten nicht in einer<br />

öffentlichen Schnittstelle erscheinen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

326


2. Nachrichten nach außen können die Umgebung ändern:<br />

public class Umweltverschmutzung {<br />

public void nurlokal( Object mo ) {<br />

do_something_good();<br />

if( mo instanceof Atmosphere )<br />

((Atmosphere) mo).pollute();<br />

}<br />

}<br />

Wie beschreibt man die Auswirkungen auf die Umgebung?<br />

Insbesondere auch die Invarianten der Umgebung.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

327


3. Für konformes Verhalten reicht Typkorrektheit nicht aus:<br />

public class Superklasse<br />

{ public int a = 0;<br />

public void dincrA() { a++; }<br />

}<br />

public class Subklasse extends Superklasse<br />

{ public void dincrA() { a--; }<br />

}<br />

Macht es Sinn, ein Subklasse-Objekt anstelle eines<br />

Superklasse-Objekts zu verwenden?<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

328


Lernziele:<br />

• Spezifikationstechniken<br />

• Beschreibung von Programmbausteinen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

329


4.1 Spezifikation von Typen 330<br />

4.1 Spezifikation von Typen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 331<br />

Ziel:<br />

Spezifikation der Eigenschaften eines Typs unabhängig von<br />

seiner/seinen Implementierungen.<br />

Problematik:<br />

• Vokabular/Framework zur Formulierung der Eigenschaften<br />

• Information Hiding: private und geschützte<br />

Implementierungsteile können nicht in öffentlicher<br />

Spezifikation benutzt werden.<br />

• Zusammenspiel zwischen deklarativer Spezifikation und<br />

objektorientierter Implementierung<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 332<br />

Ansätze:<br />

• Spezifikation mit programmiersprachlichen Mitteln<br />

• Spezifikation mit erweiterten programmiersprachlichen<br />

Mitteln unter Einhaltung der Ausführbarkeit<br />

• Spezifikation mit abstrakteren Sprachmitteln<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 333<br />

Vorgehen:<br />

• Leichte Spezifikationen<br />

• Spezifikation einzelner Objekte<br />

◦ Invarianten<br />

◦ Verhalten von Methoden<br />

◦ Umgebungseigenschaften<br />

• Spezifikation mit abstrakten Variablen<br />

◦ abstrakte Variablen<br />

◦ Abstraktionsfunktionen<br />

◦ abstrakte Spezifikation von Umgebungseigenschaften<br />

• Spezifikation zusammenhängender Objekte<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 334<br />

Dabei betrachten wir als Sprachmittel ausführbare<br />

Spezifikationen in JML , der Java Modelling Language.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 335<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

4.1.1 Leichte Spezifikationen


4.1 Spezifikation von Typen 336<br />

Definition(leichte Spezifikation):<br />

Eine leichte Spezifikation beschreibt wichtige Eigenschaften<br />

von Objekten und Methoden, die ohne großen Aufwand<br />

beschrieben werden können.<br />

Leichte Spezifikationen streben nicht die vollständige<br />

Beschreibung relevanten Verhaltens an.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 337<br />

Beispiel(leichte Spezifikation):<br />

public class Bag {<br />

//@ requires input != null;<br />

public Bag(int[] input) {<br />

n = input.length;<br />

a = new int[n];<br />

System.arraycopy(input, 0, a, 0, n);<br />

} ...<br />

}<br />

Leichte Spezifikationen sind insbesondere ein präzises<br />

Dokumentationsmittel.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 338<br />

Bemerkung:<br />

Leichte Spezifikationen können auch zur Annotation privater<br />

Programmelemente verwendet werden, um die Lesbarkeit<br />

oder Prüfbarkeit von Programmen zu verbessern.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 339<br />

Beispiel(leichte Spezifikation):<br />

public final<br />

class String implements ... {<br />

/** Used for character storage. */<br />

//@ private invariant value != null ;<br />

private char value[];<br />

/** First index of the storage used. */<br />

//@ private invariant offset >= 0<br />

private int offset;<br />

/** Number of characters in the String */<br />

//@ private invariant count >= 0 ;<br />

private int count;<br />

/*@ private invariant<br />

@ offset + count


4.1 Spezifikation von Typen 340<br />

4.1.2 Spezifikation einzelner Objekte<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 341<br />

Vereinfachende Annahmen:<br />

• Spezifikationen hängen nur von dem Zustand jeweils eines<br />

Objekts ab.<br />

• Relevante Attribute sind dem Anwender bekannt.<br />

• Methoden ändern nur das Objekt, auf dem sie aufgerufen<br />

wurden.<br />

• Kein Subtyping, keine Vererbung.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 342<br />

Spezifiziere:<br />

• die möglichen Zustände der Objekte durch Invarianten<br />

über den Attributwerten;<br />

• das Verhalten von Methoden durch die von ihnen<br />

vorgenommenen Änderungen der Attributwerte;<br />

• Umgebungseigenschaften durch Angabe, welche<br />

Attributwerte von Methoden nicht verändert werden.<br />

Beispiel:<br />

public class Point {<br />

/** Koordinaten */<br />

/*@ spec_public @*/ private float x, y;<br />

private float dist;<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 343<br />

Invarianten<br />

Invarianten spezifizieren die Bereichseinschränkungen für die<br />

Attributwerte und die Beziehungen zwischen Attributwerten.<br />

Beispiel(Invarianten):<br />

public class Point {<br />

...<br />

//@ public invariant x >= 0.0 && y >= 0.0 ;<br />

}<br />

/*@ private invariant<br />

@ dist == Math.sqrt(x*x+y*y) ;<br />

@*/<br />

...<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 344<br />

Verhalten von Konstruktoren und Methoden<br />

Konstruktoren müssen die Invarianten etablieren.<br />

Methoden müssen die Invarianten erhalten.<br />

Die Vorbedingung für ihre Anwendung und ihr Einfluss auf<br />

die Attributwerte ihres Zielobjektes und ihr Ergebnis werden<br />

mit Vor- und Nachbedingungen spezifiziert.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 345<br />

Beispiel(Verhalten von Konstruktoren und Methoden):<br />

public class Point {<br />

...<br />

/** Erzeugen eines Punktes */<br />

/*@ public normal_behavior<br />

@ requires x >= 0.0 && y >= 0.0 ;<br />

@ ensures this.x == x && this.y == y;<br />

@ also<br />

@ public exceptional_behavior<br />

@ requires x < 0.0 || y < 0.0 ;<br />

@ signals (IllegalArgumentException)<br />

@*/<br />

public Point ( float x, float y ) { ... }<br />

/*@ public normal_behavior<br />

@ ensures \result == this.x ;<br />

@*/<br />

public float getX() { ... }<br />

...<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


}<br />

4.1 Spezifikation von Typen 346<br />

/** Entfernung vom Ursprung */<br />

/*@ public normal_behavior<br />

@ ensures \result == Math.sqrt(x*x+y*y);<br />

@*/<br />

public float distance() { ... }<br />

/** Verschieben dieses Punktes */<br />

/*@ public normal_behavior<br />

@ requires x+dx >= 0.0 && y+dy >= 0.0 ;<br />

@ ensures x == \old(x)+dx && y == \old(y)+dy ;<br />

@ also<br />

@ public exceptional_behavior<br />

@ requires x+dx < 0.0 || y+dy < 0.0 ;<br />

@ signals (IllegalArgumentException)<br />

@*/<br />

public void move( float dx, float dy ){ ...}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 347<br />

Bemerkung:<br />

• Vor- und Nachbedingungsspezifikationen liefern keine<br />

vollständige Aussage darüber, was sich verändert (z.B.<br />

bzgl. Attribut dist bei Ausführung von move).<br />

• Sie liefern keine Aussage darüber, was sich nicht verändert.<br />

• Obiges Beispiel ist keine zulässige JML-Spezifikation (s.u.).<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 348<br />

Spezifikation von Umgebungseigenschaften<br />

Veränderungsspezifikationen beschreiben, welche Variablen<br />

ihren Wert bei Ausführung einer Methode nicht verändern,<br />

indem sie die Variablen spezifizieren, die sich ändern dürfen.<br />

Grund für indirektes Vorgehen:<br />

• Es gibt weniger Variablen, die sich ändern.<br />

• Im Allg. sind nicht alle Variablen des Programms bekannt.<br />

Damit ist insbesondere spezifiziert, welche Eigenschaften der<br />

Umgebung (engl. frame properties) erhalten bleiben.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 349<br />

Spezifikationsmittel:<br />

Veränderungsklausel (modifies, assignable clause):<br />

assignable 〈Liste bedingter Variablenausdrücke〉<br />

Bespiele:<br />

assignable x, this.a, p.a.b<br />

assignable x, this.a if(this==p)<br />

Bemerkung:<br />

Schlüsselwort modifies ist gleichbedeutend mit<br />

assignable.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 350<br />

Bedeutung:<br />

Eine Methode bzw. ein Konstruktor darf nur an Instanzoder<br />

Klassenvariable zuweisen, die<br />

• in der Veränderungsklausel genannt ist und deren<br />

zugehörige Bedingung im Vorzustand erfüllt ist oder<br />

• die erst während der Methodenausführung allokiert werden.<br />

Fehlt eine Veränderungsklausel, hat es die gleiche Bedeutung<br />

wie eine Veränderungsklausel mit leerer Liste.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 351<br />

Beispiel(Spezifikationsmittel):<br />

public class Point {<br />

...<br />

/*@ public normal_behavior<br />

@ requires x >= 0.0 && y >= 0.0 ;<br />

@ assignable this.x, this.y ;<br />

@ ensures this.x == x && this.y == y;<br />

@ also<br />

@ private normal_behavior<br />

@ requires x >= 0.0 && y >= 0.0 ;<br />

@ assignable dist ;<br />

@ also<br />

@ public exceptional_behavior<br />

@ requires x < 0.0 || y < 0.0 ;<br />

@ signals (IllegalArgumentException)<br />

@*/<br />

public Point ( float x, float y ) { ...}<br />

...<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


}<br />

4.1 Spezifikation von Typen 352<br />

/*@ public normal_behavior<br />

@ ensures \result == this.x ;<br />

@*/<br />

public float getX() { ... }<br />

...<br />

/*@ public normal_behavior<br />

@ requires x+dx >= 0.0 && y+dy >= 0.0;<br />

@ assignable x, y ;<br />

@ ensures x == \old(x)+dx && y == \old(y)+dy ;<br />

@ private normal_behavior<br />

@ requires x+dx >= 0.0 && y+dy >= 0.0;<br />

@ assignable dist ;<br />

@ also<br />

@ public exceptional_behavior<br />

@ requires x+dx < 0.0 || y+dy < 0.0 ;<br />

@ signals (IllegalArgumentException)<br />

@*/<br />

public void move( float dx, float dy ){ ...}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 353<br />

Bemerkung:<br />

Private Veränderungsklauseln sind unwichtig für die<br />

Dokumentation der öffentlichen Schnittstelle, aber nötig für<br />

das Prüfwerkzeug.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 354<br />

4.1.3 Spezifikation mit abstrakten Variablen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 355<br />

Abstrakte Variablen/Attribute werden zur Spezifikation<br />

benötigt, wenn<br />

• konkrete Attribute nicht deklariert sind oder<br />

• die Zugreifbarkeitsregeln die Verwendung konkreter<br />

Attribute in Spezifikationen nicht gestatten oder<br />

• Austauschbarkeit der Implementierung erreicht werden soll.<br />

Syntax: Abstrakte Variablen/Attribute werden in JML wie<br />

Attribute, allerdings mit dem zusätzlichen Schlüsselwort<br />

model als Modifikator vereinbart. In JML haben abstrakte<br />

Attribute einen Java-Typ.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 356<br />

Bedeutung:<br />

Abstrakte Attribute hängen von konkreten Attributen oder<br />

anderen abstrakten Attributen ab.<br />

Die Abhängigkeit muss in einer Abhängigkeitsklausel<br />

spezifiziert werden.<br />

Der Wert von einem abstrakten Attribut a eines Objekts<br />

ergibt sich aus den Werten der Attribute, von denen a<br />

abhängt. Wie er sich berechnet, wird in einer Repräsentationsklausel<br />

festgelegt.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 357<br />

Beispiel(Abstrakte Attribute):<br />

public class Point {<br />

/** Koordinaten */<br />

//@ public model float x, y;<br />

//@ public invariant x >= 0.0 && y >= 0.0;<br />

private double dist, angle ;<br />

/*@ private invariant dist >= 0.0<br />

@ && 0.0


4.1 Spezifikation von Typen 358<br />

Abstrakte Variablen und<br />

Umgebungseigenschaften<br />

Das Recht, eine abstrakte Variable a verändern zu dürfen,<br />

impliziert das Recht, alle konkreten Variablen zu ändern, von<br />

denen a abhängt.<br />

Beispiel(Abstrakte Variablen und Umgebungseigenschaften<br />

Der Konstruktor Point darf dist und angle verändern:<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 359<br />

public class Point {<br />

/*@ public normal_behavior<br />

@ requires x >= 0.0 && y >= 0.0 ;<br />

@ assignable this.x, this.y ;<br />

@ ensures this.x == x && this.y == y;<br />

@ also<br />

@ public exceptional_behavior<br />

@ requires x < 0.0 || y < 0.0 ;<br />

@ signals (IllegalArgumentException)<br />

@*/<br />

public Point ( float x, float y ) { ...}<br />

/*@ public normal_behavior<br />

@ ensures \result == this.x ;<br />

@*/<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


}<br />

4.1 Spezifikation von Typen 360<br />

public float getX() { ... }<br />

/*@ public normal_behavior<br />

@ requires x+dx >= 0.0 && y+dy >= 0.0;<br />

@ assignable x, y ;<br />

@ ensures x == \old(x)+dx && y == \old(y)+dy ;<br />

@ also<br />

@ public exceptional_behavior<br />

@ requires x+dx < 0.0 || y+dy < 0.0 ;<br />

@ signals (IllegalArgumentException)<br />

@*/<br />

public void move( float dx, float dy ){ ...}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 361<br />

Bemerkung:<br />

• Die Spezifikation der Veränderung von dist ist nicht mehr<br />

nötig, da x und y von dist abhängen.<br />

• Die Gleichheit in den Zusicherungsklauseln ist<br />

problematisch.<br />

Mit dem folgendem Beispiel demonstrieren wir die Spezifikation<br />

eines Typs, für den keine Attribute deklariert sind.<br />

Die Spezifikation benutzt einen komplexeren, in JML<br />

vordefinierten seiteneffektfreien Typ JMLObjectSequence:<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 362<br />

Beispiel(abstrakte Variablen):<br />

//@ model import org.jmlspecs.models.*;<br />

public abstract class UnboundedStack {<br />

/*@ public model JMLObjectSequence theStack<br />

@ initially theStack != null && theStack.isEmpty();<br />

@*/<br />

//@ public invariant theStack != null;<br />

/*@ public normal_behavior<br />

@ requires !theStack.isEmpty();<br />

@ assignable theStack;<br />

@ ensures theStack.equals( \old(theStack.trailer()));<br />

@*/<br />

public abstract void pop( );<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


}<br />

4.1 Spezifikation von Typen 363<br />

/*@ public normal_behavior<br />

@ assignable theStack;<br />

@ ensures theStack.equals( \old(theStack.insertFront(x)));<br />

@*/<br />

public abstract void push(Object x);<br />

/*@ public normal_behavior<br />

@ requires !theStack.isEmpty();<br />

@ ensures \result == theStack.first();<br />

@*/<br />

public abstract Object top( );<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 364<br />

package org.jmlspecs.models;<br />

public /*@ pure @*/ class JMLObjectSequence<br />

implements JMLCollection<br />

{<br />

public /*@ pure @*/<br />

boolean equals(Object obj) { ... }<br />

public /*@ pure @*/<br />

boolean isEmpty() { ... }<br />

public /*@ pure @*/<br />

Object first()<br />

throws JMLSequenceException { ... }<br />

public /*@ pure @*/<br />

/*@ non_null @*/ JMLObjectSequence<br />

insertFront(Object item)<br />

throws IllegalStateException { ... }<br />

...<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 365<br />

Methoden sind pure, wenn sie keine Seiteneffekte haben<br />

(assignable \nothing).<br />

Konstruktoren sind pure, wenn sie nur Objektattribute<br />

verändern und ansonsten keine Seiteneffekte haben.<br />

Klassen- und Schnittstellentypen, die als pure deklariert sind,<br />

dürfen nur pure Methoden und Konstruktoren haben.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 366<br />

4.1.4 Spezifikation zusammenhängender Objekte<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 367<br />

Objekte erbringen ihre Funktionalität meist im Zusammenwirken<br />

mit anderen Objekten. Wir betrachten hier die Fälle:<br />

• Aggregation<br />

• Komposition<br />

• Rekursive Objektbeziehungen<br />

Aggregation:<br />

Aggregation modelliert eine hat-ein-Beziehung zwischen<br />

einem Objekt X und Teilen von X. Teilobjekte sind<br />

üblicherweise außerhalb von X bekannt und zugreifbar;<br />

sie können auch Teil anderer Objekte sein.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 368<br />

Bemerkung:<br />

Die Zugreifbarkeit von außen ist problematisch, da<br />

Invarianten des aggregierenden Objekts verletzt werden<br />

können.<br />

Beispiel(Aggregation):<br />

public class Line {<br />

public /*@ non_null @*/ Point left,right;<br />

//@ public invariant left != right ;<br />

//@ public invariant left.x


}<br />

4.1 Spezifikation von Typen 369<br />

/*@ public normal_behavior<br />

@ requires p1 != null && p2 != null &&<br />

@ p1 != p2;<br />

@ assignable left, right;<br />

@ ensures ((left == p1 && right == p2)<br />

@ || (left == p2 && right == p1))<br />

@ && linebreadth == 1 && ... ;<br />

@*/<br />

public Line( Point p1, Point p2 ) { ...}<br />

...<br />

/*@ public normal_behavior<br />

@ ensures \result == left ;<br />

@*/<br />

public Point getLeft() { ... }<br />

/*@ public normal_behavior<br />

@ ensures \result == ... ;<br />

@*/<br />

public float length() { ... }<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 370<br />

Beachte:<br />

• Ein Punkt kann zu mehreren Linien gehören.<br />

• Die zweite Invariante kann durch Verschieben eines der<br />

Endpunkte verletzt werden. Deshalb besser:<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 371<br />

public class Line {<br />

public /*@ non_null @*/ Point from,to;<br />

//@ public invariant from != to ;<br />

public /*@ non_null @*/ Color linecolor;<br />

public int linebreadth ;<br />

/*@ public normal_behavior<br />

@ requires p1! = null && p2 != null &&<br />

@ p1 != p2<br />

@ assignable from, to;<br />

@ ensures form == p1 && to == p2<br />

@ && linebreadth == 1 && ...<br />

@ ...<br />

@*/<br />

public Line( Point p1, Point p2 ) { ...}<br />

...<br />

/*@ public normal_behavior<br />

@ ensures \result ==<br />

@ from.x


4.1 Spezifikation von Typen 372<br />

Komposition:<br />

Komposition modelliert eine exklusive Besitzerbeziehung<br />

zwischen einem Objekt X und seinen Teilen.<br />

Teilobjekte sind üblicherweise außerhalb von X bekannt und<br />

eingeschränkt zugreifbar; sie dürfen nicht direkter Teil<br />

mehrerer Objekte sein.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 373<br />

Beispiel(Komposition):<br />

Wir betrachten eine Klasse für Streckenzüge, die aus Linien<br />

zusammengesetzt sind.<br />

Die Streckenzüge lassen sich von außen durch Verschieben<br />

der Punkte verändern.<br />

Line<br />

from:<br />

to:<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

Polyline<br />

Line<br />

from:<br />

to:<br />

Point Point Point


4.1 Spezifikation von Typen 374<br />

Um zu verhindern, dass ein Line-Objekt Teil zweier<br />

Polylinien wird, kann man:<br />

• die Linien kapseln;<br />

• den Einbau von Linien kontrollieren.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 375<br />

Rekursive Objektbeziehungen:<br />

Die Eigenschaften und Invarianten rekursiver Klassen<br />

erstrecken sich oft über eine unbegrenzte Anzahl von<br />

Objekten.<br />

Für ihre Spezifikation benötigt man meist Hilfsfunktionen.<br />

Beispiel(rekursive Klasse):<br />

public class IntList {<br />

private int elem;<br />

private IntList next;<br />

//@ private invariant !this.reach(next) ;<br />

/*@ pure @*/ boolean reach( IntList il ){<br />

// aber wie beschreibe ich reach<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.1 Spezifikation von Typen 376<br />

Bemerkung:<br />

Obiges Beispiel zeigt:<br />

• Schranken der Ausdruckskraft der demonstrierten<br />

Spezifikationstechnik;<br />

• Problematik der Verwendung partieller Prädikate.<br />

• Eine allgemeine Spezifikationsmethode für rekursive<br />

Klassen fehlt noch.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 377<br />

4.2 Konformität von Subtypen<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 378<br />

Die Subtypbeziehung wird in Programmiersprachen meist<br />

rein syntaktisch verstanden:<br />

Was muss ein Subtypobjekt für Eigenschaften haben, damit<br />

an Stellen, an denen Supertypobjekte erwartet werden,<br />

• keine Typfehlern auftreten und<br />

• zu Methodenaufrufen immer geeignete Methodenimplementierungen<br />

existieren.<br />

Was bedeutet es semantisch, ein Subtyp zu sein?<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 379<br />

Probleme:<br />

Der Subtyp soll eine Spezialisierung des Supertyps sein. Auf<br />

Basis der operationellen Semantik lässt sich Spezialisierung<br />

nur schwer definieren:<br />

• Spezialisierung von abstrakten Typen<br />

• Erweiterung des Zustandsraums<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 380<br />

Ansatz:<br />

Definiere die Subtypbeziehungen auf Basis der<br />

Spezifikationen:<br />

• Jedes Subtypobjekt muss die Spezifikationen der<br />

Supertypen erfüllen.<br />

• Für Vor- und Nachbedingungsspezifikationen:<br />

◦ pre[Supertyp] => pre[Subtyp]<br />

◦ post[Subtyp] => post[Supertyp]<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 381<br />

Vorgehen:<br />

• Vor- und Nachbedingungsspezifikation ohne abstrakte<br />

Variablen und Abstraktion<br />

• Vor- und Nachbedingungsspezifikation mit abstrakten<br />

Variablen und Abstraktion<br />

• Behandlung von Invarianten<br />

• Umgebungseigenschaften<br />

• Zusammenwirken der Techniken<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 382<br />

Konkrete Pre-Post-Spezifikationen<br />

Jede Vor- bzw. Nachbedingung einer Methode im Supertyp<br />

kann als Vor- bzw. Nachbedingung der entsprechenden<br />

Methode des Subtyps interpretiert werden:<br />

• Vererben der Spezifikation<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 383<br />

Subtypen ohne zusätzliche Attribute:<br />

• Ererbte Methode:<br />

◦ Spezifikation wird geerbt und nicht erweitert.<br />

•<br />

Überschreibende Methode:<br />

◦ Vorbedingung wird geerbt und nicht erweitert.<br />

◦ Nachbedingung wird geerbt und ggf. um Konjunkte erweitert, d.h.<br />

verstärkt.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 384<br />

Beispiel(Konkrete Pre-Post-Spezifikationen):<br />

class C {<br />

/*@ public normal_behavior<br />

@ requires P<br />

@ ensures Q ;<br />

@*/<br />

C m(){ ... }<br />

}<br />

class D extends C {<br />

/*@ also<br />

@ public normal_behavior<br />

@ requires P<br />

@ ensures \result instanceof D ;<br />

@*/<br />

C m(){ ... }<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 385<br />

Zusätzliche Methode:<br />

• keine Einschränkungen an Verhalten.<br />

Bemerkung:<br />

Entsprechende Spezifikationsverfeinerungen, wie hier fürs<br />

normale Verhalten gelten fürs Ausnahmeverhalten.<br />

Subtypen mit zusätzlichen Attributen:<br />

Ist der Zustandsraum im Subtyp erweitert, kann neben den<br />

oben erläuterten Spezifikationsverfeinerungen eine<br />

Ergänzung der Vorbedingung bei überschreibenden<br />

Methoden sinnvoll sein.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 386<br />

Es reicht zu verlangen, dass:<br />

• pre[Supertyp] && this instanceof Subtyp ⇒pre[Subtyp]<br />

• post[Subtyp] && this instanceof Subtyp ⇒ post[Supertyp]<br />

Bemerkung:<br />

• Diese Abschwächung setzt normalerweise voraus, dass ein<br />

Supertyp seine Subtypen kennt.<br />

• Die Problematik des erweiterten Zustandsraums ist ein<br />

wichtiges Argument für die Verwendung von Abstraktion.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 387<br />

Abstrakte Pre-Post-Spezifikationen<br />

Die Repräsentation der abstrakten Attribute durch die<br />

konkreten kann von Subtyp zu Subtyp verschieden sein.<br />

Die abstrakt formulierten Bedingungen werden dementsprechend<br />

unterschiedlich konkretisiert.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 388<br />

Beispiel(Abstrakte Pre-Post-Spezifikationen):<br />

class C {<br />

//@ public model boolean valid;<br />

//@ public model AS state;<br />

/*@ public normal_behavior<br />

@ requires valid && r(state)<br />

@ ensures q(state) ;<br />

@*/<br />

void m(){ ... }<br />

}<br />

class D extends C {<br />

private BD d;<br />

//@ private depends valid


4.2 Konformität von Subtypen 389<br />

class E extends C {<br />

private BE e;<br />

//@ private depends valid


4.2 Konformität von Subtypen 390<br />

Bemerkung:<br />

• Häufig geht man auch von einer expliziten<br />

Abstraktionsfunktion aus, die den Zustandsraum des<br />

Subtyps in den des Supertyps abstrahiert.<br />

• Die abstrakten Variablen ermöglichen zwei Arten der<br />

,,Zustandserweiterung“:<br />

◦ Überschreiben der Repräsentationsfunktion<br />

◦ zusätzliche abstrakte Variablen<br />

• Die Variationen in den Subtypen können von der<br />

Repräsentationsfunktion aufgefangen werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 391<br />

Behandlung von Invarianten<br />

Im Prinzip lassen sich Invarianten durch Vor- und<br />

Nachbedingungen ausdrücken.<br />

Spezifikationstechnisch sind sie aber wichtig, da sie es<br />

ermöglichen, in Supertypen das Verhalten zusätzlicher<br />

Subtypmethoden einzuschränken:<br />

• Invarianten von Supertypen müssen auch von zusätzlichen<br />

Subtypmethoden erfüllt werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 392<br />

Beispiel(Behandlung von Invarianten):<br />

class C {<br />

public int a = 0;<br />

//@ public invariant a >= 0;<br />

...<br />

// keine Deklaration von m<br />

}<br />

class D extends C {<br />

...<br />

void m(){ a = -1; } // verletzt Invariante<br />

...<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 393<br />

Ansatz:<br />

• Invarianten des Supertyps müssen auch von den Subtypen<br />

erfüllt werden:<br />

inv[Subtyp]⇒ inv[Supertyp]<br />

• Vorgehen:<br />

Vererbe Invarianten an Subtypen und bilde die Konjunktion<br />

mit den in den Subtypen angegebenen Invarianten.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 394<br />

Problematik:<br />

Die Invarianten gelten normalerweise nicht in jedem<br />

Zustand. Was ist ihre präzise Bedeutung? Was muss im<br />

Vorzustand eines Methodenaufrufs gelten?<br />

Für die Bedeutung von Invarianten in Spezifikationssprachen<br />

gibt es bisher keine einheitliche Lösung.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 395<br />

Semantische Varianten:<br />

1. Invariante über eingeschränkte Zustandsmenge:<br />

JML: ,,Invariants have to hold in each state outside of a<br />

public method’s execution and at the beginning and end of<br />

such execution.“<br />

2. Transformation in Vor- und Nachbedingungen:<br />

Verifikationsansätze: Invarianten müssen im Nachzustand<br />

von Konstruktoraufrufen gelten. Wenn sie im Vorzustand<br />

von Methoden gelten, müssen sie auch im Nachzustand<br />

gelten.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 396<br />

Für die Verifikation bringen beide Varianten ein Problem mit<br />

sich:<br />

Sei S ein Subtyp von T, m eine Methode in T und x eine<br />

Variable vom Typ T:<br />

... x.m(...) ...<br />

In der Verifikation wird man inv[T] als Vorbedingung<br />

voraussetzen. Als Vorbedingung der Methoden von S<br />

benötigt man aber im Allg. inv[S].<br />

Ziel ist aber die Verifikation ohne Kenntnis aller Subtypen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 397<br />

Beispiel(Behandlung von Invarianten):<br />

class C {<br />

public int a = 0;<br />

//@ public invariant a => 0;<br />

...<br />

void m(){<br />

... // erhaelt die Invariante<br />

}<br />

}<br />

class Foo {<br />

void mfoo() {<br />

... x.m() ...<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 398<br />

class D extends C {<br />

public int b = 0;<br />

//@ public invariant a > 1;<br />

//@ public invariant b => 0;<br />

...<br />

void m(){<br />

b = 4 / a ;<br />

... // erhaelt beide Invarianten<br />

}<br />

}<br />

Problem:<br />

Lege die Vorbedingung für den Aufruf von x.m() fest.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 399<br />

Lösungsansatz:<br />

Betrachte als Invariante eines Typs T die folgende Formel<br />

INV[T]:<br />

∀ Typen S: S ≤ T ⇒ ( typ(this)=S ⇒ inv[S] )<br />

wobei inv[S] bei gegebenem S die Invariante der<br />

Implementierung von S bezeichnet. Dann gilt für einen<br />

Subtyp U von T:<br />

typ(this) = U ⇒ ( inv[U] ⇔ INV[T] )<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 400<br />

Bemerkung:<br />

Darüber hinaus muss man im Allg. auch zeigen, dass eine<br />

Methode von T die Invarianten aller anderen Typen<br />

unverändert lässt.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 401<br />

Umgebungseigenschaften<br />

Die Spezifikation von Umgebungseigenschaften ist mit zwei<br />

Problemen konfrontiert:<br />

• Information Hiding: nicht alle veränderbaren Variablen<br />

können in der Spezifikation genannt werden.<br />

• Zustandserweiterung: Die Supertypspezifikation sollte<br />

unabhängig von den Implementierungen der Subtypen sein.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 402<br />

Beispiel(Umgebungseigenschaften):<br />

class C {<br />

public int a = 0;<br />

private int b = 0;<br />

public static int c = 123;<br />

...<br />

/*@ public normal_behavior<br />

@ assignable a;<br />

@*/<br />

public void m(){ a++; b++; }<br />

}<br />

class Foo {<br />

void mfoo() {<br />

... x.m() ...<br />

}<br />

}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

class D extends C {<br />

public int d = 0;<br />

...<br />

public void m(){<br />

super.m();<br />

d = 87;<br />

C.c = 4 ;<br />

...<br />

}<br />

}


4.2 Konformität von Subtypen 403<br />

Ansatz:<br />

• Verwende abstrakte Attribute/Variablen, Abhängigkeitsund<br />

Repräsentationsklauseln.<br />

• Information Hiding: Abstrakte Attribute können von nicht<br />

zugreifbaren Attributen abhängen.<br />

• Zustandserweiterung: Die Abhängigkeiten abstrakter<br />

Attribute können in Subtypen erweitert werden.<br />

(Beispiel dazu im folgenden Unterabschnitt)<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 404<br />

Zusammenwirken der Techniken<br />

Spezifikationstechniken für objektorientierte Programme<br />

verfolgen zwei Ziele:<br />

• Spezifikation von Eigenschaften durch Annotation von<br />

Programmen.<br />

• Vollständige Spezifikation von Typen und damit auch<br />

Grundlage für das Verständnis der Verhaltenskonformität<br />

bei Subtypen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 405<br />

Vorgehen:<br />

• Zusammenwirken der Techniken mit Schwerpunkt<br />

abstrakte Spezifikation an einem Beispiel<br />

• Verhaltenskonformität bei Subtypen<br />

Beispiel(Zusammenwirken der Techniken):<br />

Das behandelte Beispiel ist eine Java-Adaption des zentralen<br />

Beispiels aus:<br />

K. R. M. Leino, G. Nelson: Data abstraction and<br />

information hiding, Transactions on Programming Languages<br />

and Systems 24(5): 491-553 (2002).<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 406<br />

Reader<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

BuffReader BlankReader<br />

BlankReaderImpl


4.2 Konformität von Subtypen 407<br />

Das Beispiel demonstriert vor allem die Behandlung von<br />

Zustandserweiterungen in Subtypen.<br />

public interface Reader {<br />

//@ public model instance boolean valid;<br />

//@ public model instance Object state;<br />

/*@ public normal_behavior<br />

@ requires valid;<br />

@ assignable state;<br />

@ ensures -1


4.2 Konformität von Subtypen 408<br />

public abstract class BuffReader implements Reader {<br />

protected /*@ spec_public @*/ int lo, cur, hi;<br />

protected /*@ spec_public @*/ char[] buff;<br />

//@ public model boolean svalid;<br />

/*@ public represents valid


}<br />

4.2 Konformität von Subtypen 409<br />

/*@ public normal_behavior<br />

@ requires valid;<br />

@ assignable state;<br />

@ ensures cur == \old(cur) ;<br />

@*/<br />

public abstract void refill();<br />

//@ depends valid


4.2 Konformität von Subtypen 410<br />

Eine triviale Anwendung von BlankReader und<br />

BlankReaderImpl (s. nächste Seite):<br />

public class ReaderTest {<br />

public static void main( String[] args ) {<br />

BlankReader br = new BlankReaderImpl();<br />

br.init(1000000);<br />

}<br />

}<br />

int count = 0;<br />

int chr;<br />

do {<br />

chr = br.getChar();<br />

count++;<br />

} while( chr != -1 );<br />

br.close();<br />

System.out.println(count);<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 411<br />

public class BlankReaderImpl<br />

extends BuffReader<br />

implements BlankReader<br />

{<br />

private int num;<br />

//@ private represents svalid


}<br />

4.2 Konformität von Subtypen 412<br />

public void refill() {<br />

lo = cur;<br />

hi = Math.min( lo+buff.length, num );<br />

}<br />

public void close() {}<br />

//@ private depends state


4.2 Konformität von Subtypen 413<br />

Verhaltenskonformität bei Subtypen<br />

Bisher:<br />

• Spezifikationstechniken<br />

• Spezifikationsprobleme<br />

Weitergehendes Thema:<br />

• Was bedeutet es genau, dass sich ein Typ semantisch<br />

konform zu einem anderen verhält?<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 414<br />

Definition(konforme Subtypen):<br />

Ein Typ S ist ein (verhaltens-) konformer Subtyp von einem<br />

Typ T, wenn S-Objekte an allen wesentlichen Programmkontexten,<br />

an denen T-Objekten zulässig sind, die relevanten<br />

Eigenschaften von T-Objekten haben.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 415<br />

Problematik:<br />

• Was sind die wesentlichen Programmkontexte:<br />

x instanceof S<br />

• Was sind die relevanten Eigenschaften, wie sind sie<br />

formuliert:<br />

Information Hiding, Abstraktion, Effizienz<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 416<br />

Lösungsansatz:<br />

• Betrachte nur die Methodenschnittstelle, d.h. keine<br />

Konstruktoren, keine Information über den<br />

Implementierungstyp.<br />

• Gehe vom spezifizierten Verhalten aus, wobei bestimmte<br />

Ausführungsmodelle und Spezifikationstechniken zugrunde<br />

gelegt werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.2 Konformität von Subtypen 417<br />

Literatur:<br />

B. H. Liskov, J. M. Wing: A Behavioral Notion of<br />

Subtyping. Transactions on Programming Languages and<br />

Systems 16(6): 1811-1841 (1994).<br />

Bemerkung:<br />

• Das allgemeine Problem zur präzisen Spezifikation<br />

konformer Subtypbildung bzgl. Ausführungsmodellen wie<br />

in Java ist nicht gelöst.<br />

• Konforme Subtypbildung ist auch und gerade für die<br />

Komponentenprogrammierung von zentraler Bedeutung.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.3 Module und Modularität 418<br />

4.3 Module und Modularität<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.3 Module und Modularität 419<br />

Bisher haben wir Spezifikation auf Objekt- bzw. Klassenebene<br />

betrachtet. Hier werden zwei Aspekte angesprochen<br />

die über diese Ebene hinausgehen:<br />

4.3.1 Eigenschaften auf Modulebene<br />

4.3.2 modulare Spezifikation (vgl. Folie 178 )<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.3 Module und Modularität 420<br />

4.3.1 Eigenschaften auf Modulebene<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.3 Module und Modularität 421<br />

Ein objektorientiertes Modul besteht aus mehreren Klassen.<br />

Häufig gibt es Eigenschaften, die über Klassengrenzen<br />

hinausgehen.<br />

Modulinvarianten beschreiben Eigenschaften von<br />

Assoziationen, an denen Objekte mehrerer Klassen eines<br />

Moduls beteiligt sind.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.3 Module und Modularität 422<br />

Beispiel:<br />

Die Typen Component, Container, Window, etc. des Pakets<br />

java.awt erfüllen viele Invarianten, z.B.:<br />

• Ein Window-Objekt gehört zu keinem Container.<br />

• Ein Component-Objekt c gehört genau zu dem Container<br />

c.parent und zu keinem anderen Container.<br />

Bemerkung:<br />

Sprachkonstrukte und Techniken zur Spezifikation von<br />

Moduleigenschaften sind nur ansatzweise untersucht.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.3 Module und Modularität 423<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

4.3.2 Modulare Spezifikation


4.3 Module und Modularität 424<br />

Die Entwicklung modularer Spezifikations- und<br />

Verifikationstechniken ist von fundamentaler Bedeutung, da<br />

solche Techniken die Voraussetzung für Skalierbarkeit sind.<br />

Die Entwicklung modularer Techniken für die objektorientierte<br />

Programmierung steht noch am Anfang.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.3 Module und Modularität 425<br />

Modularität von Umgebungseigenschaften:<br />

Spezifikation durch Angabe der Variablen, die sich ändern<br />

dürfen.<br />

Problematik:<br />

• Sei m eine Methode in Modul P, die die Variable x ändern<br />

darf.<br />

• Sei y eine Variable in einem Modul Q, das P benutzt, so<br />

dass y in P nicht sichtbar ist, aber von x abhängig ist.<br />

Dann führt eine Änderung von x auch zu einer Änderung<br />

von y. Diese ist aber in P nicht erkennbar.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.3 Module und Modularität 426<br />

Beispiel(Modularität von Umgebungseigenschaften:):<br />

Wir benutzen eine Listenklasse, um eine Klasse für Mengen<br />

zu implementieren, d.h. wir stützen eine Abstraktionsebene<br />

auf eine andere ab:<br />

public abstract class List {<br />

/*@ public model non_null<br />

@ JMLObjectSequence listValue;<br />

@*/<br />

protected Node first, last;<br />

/*@ protected depends listValue


}<br />

4.3 Module und Modularität 427<br />

/*@ public normal_behavior<br />

@ requires o != null;<br />

@ modifies listValue;<br />

@ ensures listValue.equals(old(listValue.insertBack(o)));<br />

@*/<br />

public void append( Object o) {<br />

if (last==null) {<br />

first = new Node(null, null, o);<br />

last = first;<br />

} else {<br />

last.next = new Node(null, last, o);<br />

last = last.next;<br />

}<br />

}<br />

/* ... */<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


4.3 Module und Modularität 428<br />

public class Node {<br />

/*@ public model non_null<br />

@ JMLObjectSequence values;<br />

@*/<br />

public Node next, prev;<br />

public Object val;<br />

/*@ public depends values


4.3 Module und Modularität 429<br />

public abstract class Set {<br />

/*@ public model non_null<br />

@ JMLObjectSet setValue; @*/<br />

protected /*@ non_null @*/ List theList;<br />

/*@ protected depends setValue


4.3 Module und Modularität 430<br />

Abschließende Bemerkungen zu Kapitel 4:<br />

• Verschiedene Techniken zur Spezifikation von Programmund<br />

Schnittstelleneigenschaften<br />

• Problematik im Zusammenhang mit Subtypen<br />

• Testfälle können auch zur Spezifikation eingesetzt werden<br />

(JML erlaubt die Einbettung von Testfällen in<br />

Spezifikationen).<br />

• Am Ende des Entwicklungsprozesses bilden Spezifikation<br />

und Programm zwei Systembeschreibungen.<br />

• Verfeinerung von Spezifikation wurden nicht behandelt.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5. Verifikation spezifizierter<br />

Eigenschaften


5. Verifikation spezifizierter Eigenschaften<br />

5.1 Techniken zur Verifikation<br />

5.2 Verifikation durch Beweis<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

432


Definition(Verifikation):<br />

Verifikation bedeutet den Nachweis, dass Software<br />

bestimmte, explizit beschriebene Eigenschaften besitzt.<br />

Beschreibung kann erfolgen durch:<br />

• Testfälle<br />

• Spezifikation der Funktionalität (Invarianten, Vor- und<br />

Nachbedingungen, ... )<br />

• Spezifikationen nicht-funktionaler Eigenschaften, z.B.<br />

Antwortzeiten, Codegröße, ... .<br />

Verifikation prüft also die Übereinstimmung von zwei<br />

expliziten Beschreibungen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

433


5.1 Techniken zur Verifikation 434<br />

5.1 Techniken zur Verifikation<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.1 Techniken zur Verifikation 435<br />

Grundlegende Techniken zur Verifikation:<br />

• Testen mit Testfällen<br />

• Testen durch dynamisches Prüfen<br />

• erweitertes statisches Prüfen<br />

• Verifikation durch Beweis<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.1 Techniken zur Verifikation 436<br />

Testen mit Testfällen<br />

• Beschreibe das ,,Soll-Verhalten“ der Software durch eine<br />

(endliche) Menge von Eingabe-Ausgabe-Paaren bzw. von<br />

Paaren aus Eingaben und Zustandssequenzen.<br />

• Prüfe, ob die Software zu den Eingaben der Testfälle die<br />

entsprechenden Ausgaben liefert / Zustände durchläuft.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.1 Techniken zur Verifikation 437<br />

Vorteile:<br />

• Testfälle sind einfach zu verstehen; weitergehende<br />

Spezifikation ist nicht erforderlich.<br />

• Durchführung von Tests ist einfach.<br />

Nachteile:<br />

• Spezifikation ist immer unvollständig.<br />

• Problematik in der OO-Programmierung: Bestimmung der<br />

relevanten Objektgeflechte.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.1 Techniken zur Verifikation 438<br />

Testen durch dynamisches Prüfen<br />

• Beschreibe das ,,Soll-Verhalten“ der Software durch<br />

ausführbare Programmspezifikation.<br />

• Prüfe zur Laufzeit, ob die Spezifikation erfüllt ist.<br />

Dazu können beliebige Eingaben verwendet werden.<br />

Anders als beim Testen mit Testfällen wird also das<br />

Verhalten des Programms an bestimmten Stellen<br />

automatisch während der Auswertung geprüft.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.1 Techniken zur Verifikation 439<br />

Vorteile:<br />

• Fehlermeldung kann automatisiert und komfortabel<br />

gestaltet werden.<br />

• Gegenüber Testen mit Testfällen: Angabe des<br />

Ausgabeverhaltens ist nicht notwendig.<br />

• Gegenüber statischen Verfahren: Einfacher zu handhaben.<br />

Nachteile:<br />

• Gegenüber Testfällen: Spezifikation muss vorhanden sein<br />

und ist fehleranfälliger als Testfälle.<br />

• Gegenüber Verifikation durch Beweis: Unvollständigkeit<br />

und schwächere Spezifikationen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.1 Techniken zur Verifikation 440<br />

Erweitertes statisches Prüfen<br />

• Beschreibe das ,,Soll-Verhalten“ der Software durch<br />

Programmspezifikation.<br />

• Nutze alle automatische Prüftechniken zur statischen<br />

Analyse der Konsistenz von Programm und Spezifikation.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.1 Techniken zur Verifikation 441<br />

Vorteile:<br />

• Gegenüber Testen: Vollständigere Abdeckung des<br />

Verhaltens; mächtigere Spezifikationen möglich.<br />

• Gegenüber Verifikation durch Beweis: Einfacher zu<br />

handhaben, weil vollautomatisch.<br />

Nachteile:<br />

• Gegenüber Testen: Spezifikation muss höheren<br />

Ansprüchen genügen, insbesondere reichen isolierte<br />

Eigenschaften im Allg. nicht aus.<br />

• Gegenüber Verifikation durch Beweis: Unvollständigkeit<br />

und schwächere Spezifikationen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.1 Techniken zur Verifikation 442<br />

Erweitertes statisches Prüfen basiert auf recht unterschiedlichen<br />

Techniken:<br />

• statischer Daten- und Kontrollflussanalyse<br />

• Modellprüfung endl. Zustandsräume (model checking)<br />

• Automatisierung klassischer Programmbeweistechniken<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.1 Techniken zur Verifikation 443<br />

• siehe nächsten Abschnitt<br />

Verifikation durch Beweis<br />

Bemerkung:<br />

Die unterschiedlichen Verifikationstechniken ergänzen sich<br />

und können kombiniert werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 444<br />

5.2 Verifikation durch Beweis<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 445<br />

Verifikation im engeren Sinne bedeutet den Beweis<br />

spezifizierter Eigenschaften mit logischen Mitteln.<br />

Im Gegensatz zum Testen erlaubt Verifikation durch Beweis,<br />

die Korrektheit zu zeigen, d.h. insbesondere die Abwesenheit<br />

von Fehlern.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 446<br />

Prinzipieller Ansatz<br />

• Grundlage für die Beweise ist ein mathematisches oder<br />

formal-logisches Spezifikations- und<br />

Verifikationsframework.<br />

•<br />

Übersetze Spezifikationen und Programme in die Formeln<br />

des Framework.<br />

• Beweise die resultierenden Beweisverpflichtungen.<br />

Wir erläutern den Ansatz anhand eines Frameworks auf der<br />

Basis einer Hoare-Logikerweiterung.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 447<br />

Spezifikations- und Verifikationsframework<br />

Als logische Grundlage betrachten wir eine sortierte<br />

Prädikatenlogik mit algebraischen Datentypen (vgl.<br />

Abschnitt 1.2 ).<br />

Die statische Semantik der betrachteten Programmiersprache<br />

wird damit spezifiziert (vgl. Abschn. 2.2.2 ).<br />

Auf dieser Basis lassen sich Eigenschaften über Programmzustände<br />

formulieren.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 448<br />

Programmspezifikationen:<br />

• Invariante zum Typ T ( inv[T] )<br />

• Vor- und Nachbedingungsspezifikation zur Methode m in<br />

Typ T ( req[T:m], ens[T:m] )<br />

• Veränderungsklauseln ( mod[T:m] )<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 449<br />

Programmlogik:<br />

• Hoare-Logik für partielle Korrektheit mit zusätzlichen<br />

Regeln für OO-Konstrukte<br />

• Formeln sind Tripel { P } c { Q }, wobei<br />

◦ P, Q Formeln der Prädikatenlogik sind;<br />

◦ c eine Anweisung, virtuelle Methode oder Methodenimplementierung<br />

ist.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 450<br />

Definition(Methodenimplementierung):<br />

Eine Methodenimplementierung K@m ist eine Deklaration<br />

einer Methode mit Rumpf in Klasse K.<br />

Definition(virtuelle Methode):<br />

Zu jeder dynamisch zu bindenden Methode m, die ein Typ T<br />

selbst deklariert oder erbt, führen wir eine virtuelle Methode<br />

T:m ein, die das Verhalten aller Methoden m in Subtypen<br />

von T zusammenfasst.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 451<br />

Umsetzung von Programmspezifikationen<br />

Die Spezifikation eines vollständigen Programms Π wird<br />

umgesetzt in eine Menge von Tripeln. Seien:<br />

• S0 ein Typ,<br />

• m eine Methode in S0 und<br />

• S1, ..., Sk die Supertypen von S0, in denen m existiert,<br />

mit Si < Si+1<br />

• T = { T | T ist Typ in Π }<br />

• INV ⇔ <br />

T ∈T inv[T]<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 452<br />

Für S0:m ist zu zeigen:<br />

{ INV ∧ <br />

0≤i≤k req[Si:m] } S0:m { INV }<br />

{ INV ∧ <br />

0≤i≤k req[Si:m] } S0:m { <br />

0≤i≤k ens[Si:m] }<br />

sowie<br />

down(mod[Si:m]) ⊆ down(mod[Si+1:m])<br />

{ INV ∧ <br />

0≤i≤k req[Si:m] ∧ v /∈ down(mod[Sk:m]) ∧ v = Z }<br />

S0:m { v = Z }<br />

wobei down( vl: set of VAR ) die Menge aller Variablen<br />

bezeichnet, die abhängige Variablen in vl besitzen.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 453<br />

Bemerkung:<br />

Details der Umsetzung hängen sowohl von der<br />

Spezifikationssprache als auch von der verwendeten<br />

Programmlogik ab.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 454<br />

Hoare-Logik für objektorientierte Programme<br />

Zusätzlich zu den Eigenschaften für klassische prozedurale<br />

Programme muss eine Logik für moderne objektorientierte<br />

Programme mit Folgendem umgehen können:<br />

• dynamisch allozierte Objekte<br />

• Subtyping<br />

• dynamische Bindung<br />

• Ausnahmebehandlung<br />

Wir illustrieren diese Aspekte an ausgewählten Regeln für<br />

eine Teilsprache von Java.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 455<br />

Axiom für Leseanweisung:<br />

{(y = null ∧ P [$(y.a)/x]) ∨<br />

(y = null ∧ P [$〈NullP Exc〉/$, new($, NullP Exc)/exc])}<br />

x = y.a; {P }<br />

Regel für Sequenzanweisung:<br />

{P} s1 {(exc = null ∧ Q) ∨ (exc = null ∧ R)}<br />

{R} s2 {Q}<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03<br />

{P} s1 s2 {Q}


5.2 Verifikation durch Beweis 456<br />

Regeln für Methodenaufruf:<br />

{P} vm(styp(y, x = y.m(e); ), m) {Q[res/x]}<br />

{(y = null ∧ P[y/this, e/par])∨<br />

(y = null ∧ Q[$〈NullPExc〉/$, new($, NullPExc)/exc])}<br />

x = y.m(e); {Q}<br />

{P } x = y.m(e); {Q}<br />

{P [w/Z]} x = y.m(e); {Q[w/Z]}<br />

wobei w eine Programmvariable ungleich x ist und Z eine<br />

logische Variable.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


5.2 Verifikation durch Beweis 457<br />

Bemerkung:<br />

• Obige Regeln sollen wichtige Ideen demonstrieren. Auf<br />

Details und die Behandlung rekursiver Methoden muss hier<br />

verzichtet werden.<br />

• Die Korrektheit der Logik kann bzgl. der operationalen<br />

Semantik gezeigt werden.<br />

A. Poetzsch-Heffter: FASOOP Wintersemester 02/03


6. Ausblicke


• Die Entwicklung der vorgestellten Techniken ist noch im<br />

Gange:<br />

◦ Integration<br />

◦ Modulebene<br />

◦ Modularität<br />

• Wichtige zukünftige Aspekte sind außerdem:<br />

◦ Zusammenwirken mit Entwicklungsmethode<br />

◦ Integration mit Entwurfstechniken<br />

◦ Werkzeug- und weitere Sprachunterstützung<br />

MMISS: Kurztitel September 15, 2003<br />

459

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!