Objektorientierte Programmiersprachen (in Arbeit) © Günter Riedewald Die Folien sind eine...

Preview:

Citation preview

Objektorientierte Programmiersprachen (in Arbeit)

© Günter RiedewaldDie Folien sind eine Ergänzung zur Vorlesung und nur für den internen

Gebrauch konzipiert.

Literatur

Abadi, Martin, Cardelli, Luca: A Theory of Objects

Springer, 1996

Bruce, K. B.:Foundations of Object-Oriented Programming Languages: Types and Semantics

The MIT Press, 2002

Budd, Timothy: An Introduction to Object-Oriented Programming

Addison-Wesley, 2002

Brügge, B., Dutoit, A. H.: Objektorientierte Softwaretechnik mit UML, Entwurfsmustern und Java

Pearson Studium, 2004

Poetzsch-Heffter, Arnd: Konzepte objektorientierter Programmierung

Springer, 2000

Diverse Literatur zu objektorientierten Sprachen, z.B.:

Bishop, Judith: Java lernen

Addison-Wesley, 2001

Deitel, H. M., Deitel, P. J.: C++ How to Program

Prentice Hall, 1994

Goldberg, A., Robson, D.: Smalltalk-80: The Language

Addison-Wesley, 1989

Gore, Jacob: Object Structures

Building Object-Oriented Software Components with Eiffel

Addison-Wesley, 1996

Kratzer, Klaus Peter: ADA Eine Einführung für Programmierer

Hanser, 1996

Lamprecht, G.: SIMULA – Einführung in die Programmiersprache

Vieweg, 1988

Schiedermeier, R.: Programmieren mit JavaEine methodische Einführung

Pearson Studium, 2005

Bücher über Konzepte von Programmiersprachen, z.B.:

Louden, Kenneth, C.: Programmiersprachen

Grundlagen, Konzepte, Entwurf

International Thomson Publishing, 1994

Objektorientierte PrototypsprachenBlaschek, Günther:

Object-Oriented Programming with Prototypes

Springer, 1994

Entwurfsmuster in OOPSGamma, E., Helm, R., Johnson, R., Vlissides, J.:

Design Pattern: Elements of Reusable Object-Oriented Software

Addison-Wesley, 1995

Beispiel:

BEGIN CLASS liste;

BEGIN INTEGER wert; REF(liste) nachf; END;

REF(liste) l;

l :- NEW liste;

l.wert := 1; l.nachf :- NEW liste;

l.nachf.wert := l.wert + 1;

END

Beispiel: komplexe Zahlen in Simula CLASS Complex(x,y);

REAL x,y;BEGIN

REAL re,im;REAL PROCEDURE realpart;BEGIN

realpart := re;END realpart;REAL PROCEDURE imaginarypart;BEGIN

imaginarypart := im;END imaginarypart;PROCEDURE add(y); REF(Complex) y;BEGIN

re := re + y.realpart;im := im + y.imaginarypart;

END add;...

comment – Initialisierungscode;re := x;im := y;END Complex;

Beispiel: abstrakte Syntaxbäume arithmetischer Ausdrücke (Kantorovič-Bäume)

Wurzel eines Teilbaumes: Operationssymbol (codiert)

Blätter eines Teilbaums: Operanden (Konstante, Variable, Teilbaum)

CLASS form; BEGIN END;

form CLASS const(val); REAL val; BEGIN END;

form CLASS var(nam, val); TEXT nam; REAL val;

BEGIN END;

form CLASS triple(lop, op, rop);

REF(form) lop, rop; INTEGER op; BEGIN END;

REF(form) f, g, h;

f :- NEW const(10);

g :- NEW var(´g´, 9);

h :- NEW triple(NEW triple(f, plus, g), plus, f);

Liefert

+

+ 10

10 g

Beispiel als Verbund (Record)

10.0 f

lop

op plus plus

rop

nam ´g´ g

val 9.0

Vereinigung von Verbunden mit nichtleerer Oberklasse - Beispiel

CLASS klasse(a,b); REAL a, b;

BEGIN REAL x, y; ... END;

klasse CLASS klasse1(c, d); REAL c, d;

BEGIN REAL u, v;

u := c + d; v := x + y;

END;

Definitionsschachtel für NEW klasse1(1, 2, 3, 4)

a 1.0

b 2.0

x w1

y w2

c 3.0

d 4.0

u 7.0

v w1+w2

Klassendefinition circle CLASS circle(center, radius);REF(point) center; REAL radius;BEGIN

REAL PROCEDURE area;BEGIN

area := pi * radius * radius;END area;

…END circle;  Klassendefinition rectangle CLASS rectangle(center, width, height);REF(point) center; REAL width, height;BEGIN

REAL PROCEDURE area;BEGIN

area := width * height;END area;

…END rectangle;

Oberklasse closedFigure CLASS closedFigure(center);REF(point) center;VIRTUAL:

REAL PROCEDURE area;BEGIN …END closedFigure;

Neudefinition von circle closedFigure CLASS circle(radius);REAL radius;BEGIN

REAL PROCEDURE area;BEGIN

area := pi * radius * radius;END area;

…END circle;

  Neudefinition von rectangle closedFigure CLASS rectangle(width, height);REAL width, height;BEGIN

REAL PROCEDURE area;BEGIN

area := width * height;END area;

…END rectangle;

Programmstück REF(point) x,y; REF(closedFigure) f; REF(rectangle) s; REF(circle) c;x :- NEW point(0.0,0.0);y :- NEW point(1.0,-1.0);s :- NEW rectangle(x,1.0,1.0);c :- NEW circle(y,1.0);f :-s;f.area;f :-c;f.area;

Allgemeine Beziehungen zwischen Objekten

Ein Objekt X benutzt ein Objekt Y, wenn

- eine Methode von X eine Nachricht an Y schickt: mX: ...Y.n ...

- Eine Methode von X das Objekt Y

a) erzeugt: mX: ...GY ... (Generator G)

b) als Parameter übergeben bekommt: X.mX(Y...)

c) als Ergebnis zurückgibt: mX: ... return Y

Hat-ein-Beziehung:

Ein Objekt X hat ein Attribut, das das Objekt Y oder eine Referenz darauf als Wert hat.

Teil-von-Beziehung: Spezialfall der Hat-ein-Beziehung, wobei Y als Teil von X betrachtet wird.

Erreichbarkeitsbeziehung: transitive Hülle der Hat-ein-Beziehung

Ist-ein-Beziehung: Jedes Objekt o einer Klasse U ist gleichzeitig Objekt einer Oberklasse zu u.

Beispiel: Personenstruktur an der Uni Studenten: Name, Geburtsdatum, Adresse, Immatrikulationsdatum, Immatrikulationsnummer, Fachbereich, Studiengang, Fachsemester, wahrscheinliches Abschlussdatum

Wissenschaftliche Mitarbeiter: Name, Geburtsdatum, Adresse, Einstellungsdatum, Beschäftigungsnummer, befristet/unbefristet, wahrscheinliches Beschäftigungsende, Fachbereich

Nichtwissenschaftliche Mitarbeiter: Name, Geburtsdatum, Adresse, Einstellungsdatum, Beschäftigungsnummer, Fachbereich

Hochschullehrer: Name, Geburtsdatum, Adresse, Berufungsdatum, Beschäftigungsnummer, Kategorie, Fachbereich

Person

Name, Geburtsdatum, Adresse, Beschäftigungsbeginn, FB

Student Angestellte

+ Imm.-Nr., Studiengang, + Beschäftigungsnr.

Fachsemester, wahrsch.

Abschlußdatum

Wissen. Mitarbeiter Nichtwiss. Mit. HSL

+ Befristung, wahr. + Kategorie

Beschäftigungsende

Polymorphismus

Einteilung nach Stansifer:Überladung

ad hoc

implizite Umwandlung

Polymorphismus

Untertyp

universell

parametrisiert

Polymorphismus nach Programmiersprachen:

1. Nichtobjektorientiert:

- Überladene Operatoren: gleicher Name, unterschiedliche Operation

- Polymorphe Operatoren: gleicher Name, gleiche Operation auf unterschiedlichen Datentypen

- Implizite Umwandlung: automatische Typkonvertierung von Operanden gemäß syntaktischer Position

- Einschließender Polymorphismus: Operation für gegebenen Typ schließt auch Daten eines abgeleiteten Typs ein

- Parametrischer Polymorphismus: Operation für unterschiedliche Datentypen mit Typparameter

2. Objektorientiert

- Gleiche Nachricht an Objekte unterschiedlicher Klassen löst unterschiedliche Operationen aus

- Gleicher Variabler können Objekte unterschiedlicher Typen eines „Vererbungspfades“ zugewiesen werden unterschiedliche Operationen bei gleicher Nachricht (dynamisches Binden)

Erscheinungsformen in OOPS:

• Ad hoc:

a) Gleicher Name für Methoden in voneinander unabhängigen Klassen

A B

m m

a b

a.m b.m

b) Gleicher Name für zwei unterschiedliche Methoden in gleicher Klasse (mit unterschiedlicher Signatur)

c) Überschriebene geerbte Operation (Konkretisierung bei Übergang von abstrakter zu konkreter Klasse, Verfeinerung, völlig neue Implementation)

• Einschließender Polymorphismus (Vererbungspolymorphismus): Eine in einer Oberklasse definierte Methode wird auch auf die Objekte der abgeleiteten Klassen angewendet.

• Typparameter in generischen Einheiten

Statisches und dynamisches BindenKovarianz und Kontravarianz

Binden:

Hier: Zuordnung von Methoden (Operationen) zu Methodennamen (Operationssymbolen)

Statisches Binden: Binden zur Übersetzungszeit

Dynamisches Binden: Binden zur Laufzeit

Beispiel: Kovarianz, Kontravarianz

Tier TIER Ok OK

F(Tier t)

Katze KATZE HUND Hund Uk UK

F(Katze t)

Ok einObjekt = NEW Uk(...);

Hund einHund = NEW Hund;

einObjekt.F(einHund);

1. Fall:

Statisches Binden: Da einObjekt vom Typ Ok ist (Vereinbarung), muss F aus der Klasse OK genommen werden. Daher ist der Parameter vom Typ Tier. Der aktuelle Parameter einHund ist vom Typ Hund und damit Untertyp von Tier.

Dynamisches Binden: einObjekt referiert zur Laufzeit zu einem Objekt des Typs Uk (Klasse UK). Dynamisch wird deshalb F von UK mit dem formalen Parameter vom Typ Katze ausgewählt. Der Typ des aktuellen Parameters einHund ist aber Hund, welches kein Untertyp von Katze ist. Demzufolge wird ein Laufzeitfehler gemeldet.

2. Fall:

Im Programmteil wird die erste Anweisung ausgetauscht gegen

Ok einObjekt = NEW Ok(...);

Keine Differenz in den Sichten bei statischer und dynamischer Bindung

3. Fall:

Änderung des 1. Falles: F in OK bekommt den Parametertyp Katze und F in UK den Parametertyp Tier

Statisches Binden liefert einen Typfehler zur Übersetzungszeit (Auswahl von F aus Ok mit gefordertem Parametertyp Katze; Typ des aktuellen Parameters ist aber Hund). Dynamisches Binden ergibt keine Probleme (Auswahl von F aus Uk mit gefordertem Parametertyp Tier; Typ des aktuellen Parameters ist der Untertyp von Tier Hund).

Während bei den Klassen von der „größeren“ zur „kleineren“ Klasse übergegangen wird, geschieht das beim Parameter von F genau umgekehrt.

Kontravarianz

Beispiel:OK Ok einObjekt = NEW Uk(...);

Katze Ergebnis = einObjekt.g(...);

Katze g(...)

UK Für Ergebnistypen von Methoden gilt bei dynamischer Bindung das

Tier g(...) Prinzip der Kovarianz.

Smalltalk

Grundprinzipien:• Jedes Ding ist ein Objekt.• Jedes Objekt ist eine Instanz einer Klasse.• Jede Klasse ist Unterklasse einer anderen Klasse.• Jedes Objekt wird durch Nachrichten aktiviert. Klassen sind Objekte und damit Instanzen von

Metaklassen. Festlegung von Object als oberste Klasse

(Durchbrechung der unendlichen Definition)

Charakteristika von Smalltalk-Klassen:

• Enthalten streng private Instanzvariablen (Speicherung des Objektzustands)

• Enthalten ein Nachrichtenprotokoll (Nachrichtenschnittstelle): Methoden zur Änderung oder zum Lesen des Objektzustands

• Enthalten Oberklasse

• Objekterzeugung durch new

• Objektzugriff über Zeiger

Beispiel: Definition der Klasse COMPLEX Class name: COMPLEXSuperclass: ObjectInstance variables: re imMethods :

realPart re

imagPart im

setReal : xre x

setImag : y im y

+ y (COMPLEX new setReal : (re + (y realPart)))

setImag: (im + (y imagPart))...

 x (COMPLEX new setReal: 1.0) setImag: 1.0y (COMPLEX new setReal: 1.0) setImag: - 1.0z x + y

Klassenstruktur Boolean – True – FalseBoolean

ifTrue:

ifFalse:

xor:

True False

ifTrue: ifFalse: ifTrue: ifFalse:

not not

or: or:

and: and:

true false

Methodenidentifikation:Vor.: Nachricht m an Objekt o der Klasse K

a) Suche von m in K:

Erfolg, wenn m gefunden wurde

b) Fortsetzung der Suche in der Oberklasse:

Erfolg, wenn m dort vorhanden ist

Bei Misserfolg Fortsetzung in weiterer Oberklasse

c) Suche erreicht Object und m ist nicht vorhanden:

Nachricht DoesNotUnderstand: m an Objekt o und Identifikationsprozess mit DoesNotUnderstand

d) Wird erneut Object erreicht, erfolgt eine Standardfehlermeldung

Beispiel: Fachbereichscodes Class name: FachbereichscodesSuperclass: ObjectInstance variables: names, codesMethods :´´Create an instance´´new

super new. ´´Create initial empty arrays´´initialise

[names Array new: 0codes Array new: 0].

 ´´Test for empty´´isEmpty

names isEmpty. ´´Test for inclusion of a given name´´include: name

(self indexOf: name) ~= 0. 

´´Create a new entry with the given name and return index´´newIndexOf: name

[self grownames at: names size put: name names size].

 

´´Stretch table by one element and put in new name´´grow

[oldNames oldCodesoldNames namesoldCodes codesnames Array new: names size + 1codes Array new: codes size + 1names replaceFrom: 1 to: oldNames size with: oldNamescodes replaceFrom: 1 to: oldNames size with: oldCodes].

 

´´Number of table entries´´size

names size. ´´Fetch the code for a department´´at: name

[indexindex self indexOf: nameindex = 0ifTrue: [self error: ‘Error—Name not in table’]ifFalse: [ codes at: index]].

´´Install a new code; create entry if necessary´´at: name put: code

[index index self indexOf: nameindex = 0ifTrue: [index self newIndexOf: name] codes at: index put: code].

 

´´Look-up index of a given department name´´indexOf: name

[1 to: names size do:[:index (names at: index) = name ifTrue: [ index]]

0]. 

´´Ausdrücke´´dCodes Fachbereichscodes new erzeugt neue InstanzdCodes initialise initialisiert names und codesdCodes isEmpty names und codes sind leerdCodes at: ´Physics´ put: 100 Physics wird mit 100,dCodes at: ´Chemistry´ put: 110 Chemistry mit 110 unddCodes at: ´Biology´ put: 120 Biology mit 120 eingetragendCodes isEmpty die Tabelle ist nicht leerdCodes size sie enthält 3 EintragungendCodes at: ´Chemistry´ liefert 110dCodes includes ´Physics´ liefert truedCodes includes ´Computing´ liefert false

Object

MetaClass Class

ZClass Z

AClass Aerben von Metaklassen Klassen

Instanz sein von

Eiffel

Charakteristische Prinzipien und Konstrukte:• Eiffel ist streng getypt:

- Festlegung von Typen durch Deklaration

- Statische Kompatibilität

- Eindeutig bestimmbarer Typ• Typen:

- Referenztypen: Zeiger auf Objekte

- Erweiterte Typen: Objekttypen

- Basistypen: INTEGER, REAL, DOUBLE, CHARACTER, BOOLEAN

• Klassen als Implementation von ADTs und Grundlage für Objekttypen

• Klasse als Ding der Übersetzungszeit, Objekt als Ding der Laufzeit

• Vor- und Nachbedingungen für Methoden als Basis der Methode des Programming (Design) by Contract:

„{V} q {N}, p ruft q auf“ bedeutet „Wenn p die Gültigkeit der Vorbedingung V garantiert, dann garantiert auch q die Gültigkeit der Nachbedingung N.“

• Klasseninvariante, Schleifeninvariante

• Sprachkonstrukt für Ausnahmebehandlung

• Mehrfachvererbung

• Generische Klassen als Implementierung parametrisierter ADTs

• Abstrakte Klassen in Form zurückgestellter Klassen

• Gezielte Verdeckung von Merkmalen

Klassenstruktur:

[<Indexierung>]

<Klassenkopf>

[<formale generische Parameter>]

[<veraltete Klasse>]

[<Vererbung>]

[<Erzeugung>]

[<Merkmale>]

[<Invariante>]

end [--class <Klassenname>]

Beispiel: generische Klasse für Hashtabellen hash-fähiger Elementeindexing

names: h_table;access: key,direct;representation: array;size: fixed, resizable

 class HASH_TABLE[T, V HASHABLE]inherit TABLE[T, V]

redefineloadend

 creation

makefeature

remove(k: V) is--Remove entry of key krequire

valid_key: is_valid(k)do…ensure

not has(k)end; --remove

make(n: INTEGER): BOOLEAN is--Allocate space for n items…end; --make

 load …

 ok: BOOLEAN is--Was last operation successful?do

Result := control = 0end; --ok

 control: INTEGER;Max_control: INTEGER is 5;…

 invariant

0<= control; control <= Max_controlend –class HASH_TABLE

Anpassung ererbter Merkmale:

• Überschreibung:

– Überschreibbar: Signatur, Implementation, Spezifikation (Vor- und Nachbedingung)

Bedingung: Eine überschriebene Signatur muss entsprechend Konformitätsregeln konform zur alten Signatur sein; „Beachtung“ der Bedingungen.

– Gründe für ein Überschreiben: Unvollständigkeit oder Inkorrektheit für die neue Klasse oder ungenügende Effizienz

– Ankündigung durch

redefine <Merkmalsliste>

• Umbenennung:

- rename <alter Merkmalsname> as <neuer

Merkmalsname>

- Ziele:

Vermeidung von Namenskonflikten, die Ermöglichung des Zugriffs zu gleichnamigen aber unterschiedlichen Merkmalen und die Einführung sprechender Bezeichnungen

• Implementation von in den Elternklassen zurückgestellten Merkmalen:

Kennzeichnung in Elternklassen mit deferred als abstrakt und Spezifikation mit abstrakten Eigenschaften; Implementierung unter Beachtung der Typkonformitätsregel und der Bedingungen

• Löschen der Implementation eines geerbten Merkmals:

undefine <Liste von Merkmalsnamen>

Die angeführten Merkmale werden als zurückgestellt (in der Elternklasse) betrachtet.

Beispiel: Umbenennung

class C

inherit

A

rename f as g

end;

B

feature

h(x,y:T) is

do

g(x,y) Verwendung von f aus A

f(y) Verwendung von f aus B

end

end –class C

Beispiel: abstrakte Klasse

deferred class COMPARABLE

feature

infix ´´<´´(other: like current):

BOOLEAN is

deferred

end

end –class COMPARABLE

class STRING

inherit

COMPARABLE

redefine ´´<´´

end

feature

infix´´<´´(other: like current):

BOOLEAN is

end

end –class STRING

Vererbungshierarchie:

GENERAL

PLATFORM

ANY

...

NONE

Vererbungsrelationen:

B Eltern

C Kind (Erbe)

A A, B, C sind Vorgänger (Vorfahren) von C

A, B, C sind Nachfolger (Nachfahren) von B A

A, B sind echte Vorgänger von C

C B, C sind echte Nachfolger von A

Beispiel:inherit

C

rename

...

export {D,E,F} Die Merkmale f, g und h der Klasse C werden

f,g,h an die Klassen D, E und F „weitergegeben“.

{M,N} Die Merkmale k, l und m der Klasse C werden

k,l,m an die Klassen M und N „weitergegeben“.

redefine

...

end

Situationen mit Beachtung der Konformität:• x := y :Der Typ von y muss konform zum Typ von x sein.

• Typen aktueller Parameter müssen konform zu den Typen der entsprechenden formalen Parameter sein.

• Das Überschreiben eines ererbten Attributs muss so geschehen, dass der neue Typ konform zum alten Typ ist (Kovarianz).

• Beim Überschreiben einer Funktion muss der neue Ergebnistyp konform zum alten Ergebnistyp sein.

• Beim Überschreiben einer Routine müssen die neuen Argumenttypen konform zu den entsprechenden alten Argumenttypen sein.

Beispiele: Mehrfachvererbung (wiederholte Vererbung)

• Einfache wiederholte Vererbung

class B

inherit

A; A

feature

...

end –class B

Festlegung: A wird nur einfach geerbt.

• Ererbte Routine wird modifiziert und unter altem Namen bereitgestellt, während die alte Version einen neuen Namen bekommtclass B

inherit ...

A feature

rename make is

make as A_make do

end; A_make

A …

redefine end

make …

select end –class B

make

end

A A

make make

ererbt und B ererbt und

umbenannt überschrieben

A_make

make

• Auswahl eines Merkmals bei Ringstruktur

A

f

B C

ererbt undf überschrieben f

ererbt und D ererbt und

umbenannt umbenannt

bf

cf

a: A; b: B; c: C; d: D;

...

b := d; c := d; a := d; -- erlaubt wegen Konformität

b.f; -- Aufruf von bf

c.f; -- Aufruf von cf

a.f; -- Aufruf von bf oder cf?

Auswahl durch select-Klausel in D:class D

inherit B

rename f as bf

select bf

...

end;

Varianten der Objekterzeugung:

Voraussetzung: Klasse C definiert Objekttyp T, x sei vom Typ T

• C enthalte keine Erzeugungsprozedur:

!!x bedeutet

a) Erzeugung eines neuen Objekts als Instanz vom Typ T

b) Initialisierung aller Objektkomponenten durch Standardwerte

c) Setzen der Referenz von x auf das Objekt

• C enthalte eine Erzeugungsroutine cp:

!!x.cp(...) bedeutet

a) Erzeugung eines neuen Objekts als Instanz vom Typ T

b) Initialisierung aller Objektkomponenten durch Standardwerte

c) Aufruf von cp(...) angewendet auf das Objekt

d) Setzen der Referenz von x auf das Objekt

• Erzeugung eines Objekts vom Typ V konform mit T: !V!x oder !V!x.cp(...)

Beachte folgende Situationen:• Klassendefinition enthält keine creation-Klausel: !!

<Variable> mit Standardinitialisierung wird genutzt.

• Klassendefinition enthält leere creation-Klausel (besteht nur aus creation): Es können keine Objekte als Instanzen dieser Klasse erzeugt werden.

• Auf Klienten zugeschnittene creation-Klausel (wie feature-Klausel).

• Eine Erzeugungsroutine verliert beim Vererben ihren Erzeugungscharakter, wenn sie nicht explizit in der creation-Klausel der abgeleiteten Klasse steht.

Beispiel: komplexe Zahlen 

class COMPLEXcreation

makeComplexfeature {NONE}

re, im: REAL; -- nicht exportiertfeature

makeComplex(x, y:REAL) isdo

re := x;im := y;

end; --makeComplex 

realPart: REAL isdo Result := re end;

 imaginaryPart: REAL is

do Result := im end;

add(y: COMPLEX) isdo

re := re + y.realPart;im := im + y.imaginaryPart;

end; --add

 

 subtract(y: COMPLEX) is

dore := re - y.realPart;im := im - y.imaginaryPart;

end; --subtract 

negate isdore := -re;im := -im;end; --negate

 multiply(y: COMPLEX) is

local r, i: REAL;dor := re * y.realPart – im * y.imaginaryPart;i := im * y.realPart + re * y.imaginaryPart;re := r; im := i;end; --multiply

 divide(y: COMPLEX) is ...

end; --class COMPLEX

x, y, z: COMPLEX;…!!x.makeComplex(1.0, 1.0) ; --erzeuge ein Objekt mit der komplexen Zahl

--1.0 + i 1.0 und setze eine Referenz von x zu --ihm

!!y.makeComplex(2.0, -1.0); --erzeuge ein Objekt mit der komplexen Zahl--2.0 – i1.0 und setze eine Referenz von y zu ihm

z := clone(x); --z zeigt auf eine Kopie des von x gezeigten--Objekts

z.add(y); --z zeigt auf die Summe der von x und y--gezeigten komplexen Zahlen

Zusicherungen in Eiffel:

• Klasseninvariante: Eigenschaften aller Objekte der Klasse zu stabilen Situationen

• Schleifeninvariante:

- Zweck der Schleife in Form von Beziehungen zwischen Programmvariablen

- gilt vom Eintritt bis zum Verlassen der Schleife (bei Verlassen gilt zusätzlich Abbruchbedingung)

- variant-Klausel kontrolliert über Integer-Ausdruck Erreichung des Schleifenendes (Verminderung in jedem Durchlauf, aber nie negativ)

- Schleifenstruktur:

from

... Initialisierung

invariant

... Schleifeninvariante

variant

... Variant-Klausel

until

... Bedingung für Schleifenende

loop

... Schleifenkörper

end

• check-Klausel: an allen Anweisungsstellen erlaubt zur Formulierung von lokalen Eigenschaften

• Vor- und Nachbedingungen für RoutinenProzedurdefinition:

<Prozedurname>(<Argumente>) is

require

... Vorbedingung

local

... Deklaration lokaler Elemente

do

... Prozedurkörper

ensure

... Nachbedingung

end

Ausnahmesituationen:

• Falscher Alarm: Meldung einer Ausnahme ohne Einfluss auf weitere Abarbeitung normale Fortsetzung

• Wiederaufnahme: Softwarekomponente mit vorbedachten Alternativen für den Ausnahmefall Fortsetzung nach ausgewählter Alternative

• Organisierte Panik: keine Möglichkeit der Vertragserfüllung Objekte werden in akzeptablen Zustand versetzt und es erfolgt eine Misserfolgsmeldung an Kunden

try_once_or_twice is--Solve problem using method 1 or, if unsuccessful, method 2localalready_tried: BOOLEAN;

doif not already_tried then method_1 else method_2 endrescueif not already_tried then already_tried := true;retryend

end –try_once_or_twice

try_and_record is--Attempt to solve problem using method 1 or, if unsuccessful, method 2.--Set impossible to true if neither method succeeded, false otherwise.local

already_tried: BOOLEAN;do

if not already_tried then method_1elseif not impossible then method_2end

rescueif already_tried then impossible := true end;already_tried := true;retry

end –try_and_record

Java

Ziele und Charakteristika:

• Softwareaustausch zwischen unterschiedlicher Hardware

• Als selbständige OOPS entwickelt, aber mit imperativen Sprachkonstrukten

• Elementare Datentypen wie in imperativen Sprachen, aber in Klassen einpackbar (wrapper)

• Gewisse Möglichkeiten der Metaprogrammierung

• Parallelarbeit durch Ausführungsstränge (threads)

• Objektlokale und klassenlokale Variablen und Methoden

• Schnittstellenkonzept

• Applet-Nutzung

• Netzprogrammierung

Klasse, Objekt

Klasse: neuer Objekttyp + Implementierung

Aufbau einer Klasse:[<Modifikatorenliste>] class <Klassenname>

{<Liste von Attribut-, Konstruktor- und Methodendeklarationen>}

Methodendeklaration:[<Modifikatorenliste>] <Ergebnistyp> <Methodenname>

([<Parameterliste>])

[<throws-Deklaration>] <Methodenrumpf>

Konstruktor:

• Dient der Erzeugung von Objekten und der Initialisierung der objektlokalen Variablen

• Konstruktorname = Klassenname

• Bereitstellung durch Nutzer oder Standard

• Aufruf: new <Klassenname> (<aktuelle Parameter>)

Programm:

• Kollektion von Klassen

• Eine Klasse enthält Klassenmethode main:

public static void main (String[ ] argf) {...}

Imperative KonstrukteWerte, Variablen, Ausdrücke

Werte:

• Elemente eines Datentyps

• Objektreferenzen

• Referenz null

Operationen:

• Auf Objekten oder deren Referenzen

• Auf Basisdatentypen

• Auf allen Datentypen (z.B. ==, !=, =)

Zuweisung <Variable> = <Ausdruck>:

• Berechnung des Ausdruckwertes und Zuweisung zur Variablen auf der linken Seite

• Wert der Zuweisung = Wert des Ausdrucks

Operandentypen: bei ungleichen Typen

• Implizite Konvertierung: ganzahlige Typen in größere Bereiche oder Gleitkomma

• Explizite Konvertierung:

(<gewünschter Typ>) <Ausdruck>

(Gewünschter Typ und Ausdruckstyp müssen miteinander vereinbar sein.)

Imperative KonstrukteAnweisungen, Blöcke

Anweisungen:

• Ausdruck (Zuweisung, Methodenaufruf, arithmetischer Ausdruck, logischer Ausdruck)

• Bedingte Anweisungen:

- if (<logischer Ausdruck>) <Anweisung>

- if (<logischer Ausdruck>)

<Anweisung1> else <Anweisung2>

• Mehrfache Alternative (switch-Anweisung)

• Schleifen:

- while (<logischer Ausdruck>) <Anweisung>

- do <Anweisung> while (<logischer Ausdruck>)

- for (<Init-Ausdruck>; <logischer Ausdruck>; <Ausdruck>) <Anweisung>

Block:

• Variablendeklarationen und Anweisungen gemischt und eingeschlossen in { }

• Zählt als zusammengesetzte Anweisung

Beispiele:• result = 1;

for (i = 2; i <=n; i = i + 1) result = result * i;

• i = 2;

while (i <= n)

{result = result * i; i = i + 1;}

• switch (n) {

case 0:...; break;

case 1:...; break;

...

case 10:...; break;

default:...; }

Spezielle Anweisungen:

• break: Verlassen der umfassenden Anweisung (Beispiel siehe oben)

• return [<Ausdruck>]: Verlassen eines Methodenrumpfes mit eventuellem Ergebnis

Ausnahmebehandlung

Aufbau der try-Anweisung:

try

<Block> enthält Anweisungen, die eine

Ausnahme verursachen

könnten

catch (<Ausnahmetyp> <Bezeichner>) <Block>

...

catch (<Ausnahmetyp> <Bezeichner>) <Block>

[finally <Block>]

Beispiel:• int m;

String str = ´´007L´´;

try {

m = Integer.parseInt(str);

}

catch (NumberFormatException e) {

System.out.println(´´str keine int-Konstante´´);

m = 0}

System.out.println(m);

Allgemeine Abarbeitung der try-Anweisung:

• Fehlerfreie Ausführung des try-Blocks:

- Ausführung des finally-Blocks

- Normale Terminierung der try-Anweisung und Fortsetzung mit nachfolgender Anweisung

• Abrupte Beendigung des try-Blocks durch Ausnahme Ex:

- Passender catch-Block existiert:

1. Ausführung des catch-Blocks

2. Ausführung des finally-Blocks

3. Normale Terminierung der try-Anweisung und Fortsetzung mit nachfolgender Anweisung

- Sonst (kein passender catch-Block):

1. Ausführung des finally-Blocks

2. Wird die try-Anweisung von weiterer try-Anweisung umfasst, erfolgt Weitergabe von

Ex an sie; ansonsten erfolgt abrupte Terminierung mit Ausnahme Ex.

Direkte Auslösung einer Ausnahme mit throw-Ausdruck.

try-Block Ausnahme

Keine Ausnahme

catch-Block

finally-Block

Propagierung von Ausnahmen:

• Innerhalb von Hierarchien von Throw-Blöcken zum unmittelbar umfassenden throw-Block

• Von aufgerufener Methode zum Aufrufer durch throws-Deklaration im Methodenkopf

[<Modifikatorenliste>] <Ergebnistyp> <Methodenname> ([<Parameterliste>])

[<throws-Deklaration>] <Methodenrumpf>

Strukturen mit Klassen, Sichtbarkeit

Strukturen:

• Paket als Zusammenfassung logisch zusammengehöriger Klassen

• Vererbungsstruktur für Klassifikation

• Verschachtelung von Klassen (innere Klassen) zur Erleichterung der Handhabung

Anwendungaspekte für Pakete:

• Gute Strukturierung

• Einteilung in Namensräume und Festlegung von Zugriffsrechten

• Separate Übersetzung

• Wiederverwendung von Klassen

Steuerung des Zugriffs zu Konstrukten eines Pakets:

• Kein Modifikator (default access): paketlokaler Zugriff

• public: uneingeschränkte Nutzung

• private: klassenlokaler Zugriff

• protected: Zugriff durch abgeleitete Klassen

Person

Druckbar

Student Angestellte

wissMitarbeiter nwMitarbeiter HSL

class Person {...}interface Druckbar {void drucken();}class Student extends Person

implements Druckbar {...}class Angestellte extends Person

implements Druckbar {...}class wissMitarbeiter extends Angestellte

implements Druckbar {...}class nwMitarbeiter extends Angestellte

implements Druckbar {...}class HSL extends Angestellte

implements Druckbar {...}

Typen

 

 

Basisdatentypen Referenz- oder Objekttypen

 

 

 

Klassentypen SchnittstellentypenFeldtypen

Beispiel: Dynamisches Binden für Untertypen des Schnittstellentyps Druckbar

class NumDruck{

private static int Nummer = 1;

private static void DruckMitNum(Druckbar d){

System.out.println(´´Posten´´+Nummer+´´:´´);

d.drucken(); Nummer ++;

}

}

Vererbung:• Geerbt werden alle Attribute, Methoden und inneren

Klassen der Oberklassen, falls ein Zugriff erlaubt ist

Spezialfall Konstruktoren:

Im Unterklassenkonstruktor kann direkt auf den Oberklassenkonstruktor durch super(<Parameter>) oder implizit als erste Anweisung des Unterklassenkonstruktors auf den parameterlosen Oberklassenkonstruktor zugegriffen werden.

• Anpassung einer geerbten Methode: Ersetzen durch Methode gleicher Signatur oder Zugriff auf Methode der Oberklasse durch super.<Methodenname>(<Parameter>) mit Ergänzung

• Zusätzliche Attribute, Methoden und innere Klassen

class LinkedList{private Entry header = new Entry(null, null, null);private int size = 0;LinkedList(){header.next = header;header.previous = header;}

 ListElem getLast(){…}ListElem removeLast(){…}void addLast(ListElem e){…}int size(){…}

private static class Entry{private ListElem element;private Entry next;private Entry previous;

 Entry(ListElem element, Entry next, Entry previous){…}

}}

 

LinkedList Entry 

header element nullsize 3 next

previous  Entry Entry Entry

element element elementnext next nextprevious previous previous ListElem ListElem ListElem

class MyClassIsMyCastle {private static int streetno = 169;

private static class FirstFloor {private static class DiningRoom {

private static int size = 36;private static void mymessage() {

System.out.print(´´I can access streetno´´);System.out.println(´´:´´+streetno);

}}

private static class SecondFloor {private static class Bathroom {

private static int size = 16;private static void mymess() {

System.out.print(´´I can access the ´´);System.out.print(´´dining room size: ´´);System.out.println(´´ ´´+FirstFloor.DiningRoom.size);

}}

}

public static void main(String[] argv){FirstFloor.DiningRoom.mymessage();SecondFloor.Bathroom.mymess();

}}

MyClassIsMyCastle 

streetno 169 MyClassIsMyCastle 

FirstFloor 

DiningRoom FirstFloor SecondFloor 

size 36 

mymessage DiningRoom BathRoom  

SecondFloor 

BathRoom 

size 16 

mymess  

main

class LinkedList {private Entry header = new Entry(null, null, null);private int size = 0;…private static class Entry {…}

class ListIterator {private int nextIndex = 0;private Entry next = header.next;

 boolean hasNext(){

return nextIndex != size;}

 ListElem next(){

if (nextIndex == size)throw new NoSuchElementException();

ListElem elem = next.element;next = next.next;nextIndex ++;return elem;

}}

ListIterator listIterator(){Return new ListIterator();

}}

LinkedList 

header element nullnext nullprevious null

size 0 

Entry  

ListIterator 

nextIndex 0next element

nextprevious

 hasNextnext

  listIterator

Beispiel: Anwendung des Schnittstellenkonzepts auf die Implementierung des Beobachtermusters (nach A. Poetzsch-Heffter: Konzepte objektorientierter Programmierung)

Schnittstelle:

interface Beobachter {

void steigen(Aktie a);

void fallen(Aktie a);

}

Aktienklasse:

import java.util.*;

public class Aktie {

private String name;

private int kurswert;

private ArrayList beobachterliste;

Aktie(String n, int anfangswert){

name = n;

kurswert = anfangswert;

beobachterliste = new ArrayList();

}

public void anmeldenBeobachter(Beobachter b) {

beobachterliste.add(b);

}

public String getName() {

return name;

}

public int getKurswert() {

return kurswert;

}

void setKurswert(int neuerWert) {

int alterWert = kursWert;

kursWert = neuerWert>0 ? neuerWert : 1;

ListIterator it = beobachterliste.listIterator();

if(kursWert > alterWert) {

while(it.hasNext() ) {

Beobachter b = (Beobachter)it.next();

b.steigen(this);} }

else {

while(it.hasNext() ) {

Beobachter b = (Beobachter) it.next();

b.fallen(this);}

}

}

}

Aktieninteressent:

class Kunde1 implements Beobachter {

private boolean besitzt = false;

public void fallen(Aktie a) {

if(a.getKurswert() < 300 && !besitzt) {

System.out.println(´´Kauf von ´´+a.getName() );

besitzt = true;

}}

public void steigen(Aktie a) {

if(a.getKurswert() > 400 && besitzt) {

System.out.println(´´Verkauf von ´´+a.getName() );

besitzt = false;

}}

Schlafend E/A beendet E/A-blockiert 

interrupt Zeit abgelaufen E/Asleep

  yieldNeu Rechenbereit Rechnend

start Scheduling Tot

  wait

 interrupt notify/ Monitor besetzt

notifyAllMonitor

Wartend frei Monitor-blockiert

Prozesszustände und -übergänge

terminiert

Erzeugung von Strängen:

1. Ableitung einer neuen Thread-Klasse K aus der Klasse Thread mit Überschreiben der Methode run:

class K extends Thread{

...

public void run(){

...

}

}

Thread meinThread = new K();

...

meinThread.start();

2. Ableitung einer neuen Klasse K von einer beliebigen Klasse O mit gleichzeitiger Implementierung der Schnittstelle Runnable:

class K extends O

implements Runnable

...

public void run(){

...

}

}

Runnable meinZiel = new K();

Thread meinThread = new Thread(meinZiel);

...

meinThread.start();

PACKAGE Keller_Verwaltung IS -- TypvereinbarungenTYPE Keller IS PRIVATE; -- Unterprogrammvereinbarungen FUNCTION Leer (K: Keller) RETURN Boolean;-- Leer zeigt an, ob der Keller leer ist. PROCEDURE Push (K: IN OUT Keller; Was: IN Integer);-- Ein Element wird in den Keller gefuellt. PROCEDURE Pop (K: IN OUT Keller);-- Das Element an der Kellerspitze wird entfernt. FUNCTION Read (K: Keller) RETURN Integer;-- Das Element an der Kellerspitze wird gelesen. FUNCTION Groesse (K: Keller) RETURN Natural;-- Gibt die Anzahl der Kellerelemente an.

-- AusnahmesituationenKellerueberlauf: EXCEPTION RENAMES Storage_ErrorLeerer_Keller: EXCEPTION; PRIVATE

TYPE Komponente;TYPE Komponenten_Zeiger IS ACCESS Komponente;TYPE Komponente IS RECORD

Information: Integer;Weiter: Komponenten_Zeiger;

END RECORD;TYPE Keller IS RECORD

Anker: Komponenten_Zeiger := 0;Groesse: Natural := 0;END RECORD;

END Keller_Verwaltung;

Paket X Kindpaket X.Y

Deklarationen öffentlich öffentlichprivat privat

  

Körper

GENERICSize: Positive;TYPE Item IS PRIVATE;

PACKAGE Stack ISPROCEDURE Push (E: IN Item);PROCEDURE Read (E: OUT Item);Overflow, Underflow: EXCEPTION;

END Stack;

PACKAGE BODY Stack ISTYPE Table IS ARRAY (Positive RANGE <>) OF Item;Space: Table (1..Size);Index: Natural := 0;

 PROCEDURE Push (E: Item) ISBEGIN IF Index >= Size Then RAISE Overflow END IF;

Index := Index + 1;Space (Index) := E;

END Push;

PROCEDURE Read (E: OUT Item) ISBEGIN IF Index = 0 THEN RAISE Underflow; END IF;

E := Space(Index);Index := Index – 1;

END Read;END Stack;

-         TYPE Tastenart IS (Zeichen, Funktion, Pfeil, Unbekannt); TYPE F_Nummer IS RANGE 1..10; TYPE Richtung IS (N, O, S, W); TYPE Taste (Art: Tastenart := Unbekannt) IS RECORD CASE Art IS

WHEN Zeichen Z: Character;WHEN Funktion F: F_Nummer;WHEN Pfeil R: Richtung;WHEN Unbekannt NULL;

END CASE; END RECORD;

WITH Calendar, People;PACKAGE Alert_System IS

TYPE Alert IS TAGGEDRECORD

Time_Of_Arrival: Calendar.Time;Message: Text;

END RECORD;PROCEDURE Display(A: IN Alert);PROCEDURE Handle(A: IN OUT Alert);PROCEDURE Log(A: IN Alert);

 TYPE Low_Alert IS NEW Alert WITH NULL

RECORD;

TYPE Medium_Alert IS NEW Alert WITHRECORD

Action_Officer: People.Person;END RECORD;

-- neue Handle-OperationPROCEDURE Handle(MA: IN OUT Medium_Alert);

 TYPE High_Alert IS NEW Medium_Alert WITH

RECORDRing_Alarm_At: Calendar.Time;

END RECORD;-- neue Handle-OperationPROCEDURE Handle(HA: IN OUT High_Alert);PROCEDURE Set_Alarm(HA: IN High_Alert);

 END Alert_System;

Alert  

Low_Alert Medium_Alert  

High_Alert

PACKAGE Sets ISSUBTYPE Element_Type IS Natural;TYPE Set IS ABSTRACT TAGGED NULL RECORD;

FUNCTION Empty RETURN Set IS ABSTRACT;FUNCTION Union (Left, Right: Set) RETURN Set IS ABSTRACT;FUNCTION Intersection (Left, Right: Set) RETURN Set IS

ABSTRACT;FUNCTION Unit_Set (Element: Element_Type) RETURN Set IS

ABSTRACT;PROCEDURE Take (Element: OUT Element_Type;

From: IN OUT Set) IS ABSTRACT;END Sets;

-- Private Vereinbarung des Typs Geometrisches_Objekt im Paket Geo PACKAGE Geo IS

TYPE Geometrisches_Objekt IS ABSTRACT TAGGED PRIVATE;  TYPE Pixel_Koordinaten IS

RECORDX, Y: Integer;

END RECORD ; 

TYPE Bildschirmfarbe IS RANGE 0..15 ; 

PROCEDURE Verlagere (Was: IN OUT Geometrisches_Objekt;Wohin: IN Pixel_Koordinaten);

  PROCEDURE Zeige (Was: IN Geometrisches_Objekt) IS Abstract;

PRIVATETYPE Geometrisches_Objekt IS TAGGED

RECORDFarbe: Bildschirmfarbe;Bezugspunkt: Pixel_Koordinaten;

END RECORD;END Geo;

-- Private Vereinbarung des Typs Flaechenobjekt im Paket-- Geo.Flaechenobjekte PACKAGE Geo.Flaechenobjekte IS

TYPE Flaechenobjekt IS ABSTRACT NEW Geometrisches_Objekt WITH PRIVATE; PRIVATE

TYPE Flaechenobjekt IS ABSTRACT NEWGeometrisches_Objekt WITHRECORD

Gefuellt: Boolean;END RECORD;

END Geo_Flaechenobjekte;

-- Private Vereinbarung des Typs Kreis im Paket-- Geo.Flaechenobjekte.Kreise PACKAGE Geo.Flaechenobjekte.Kreise IS

TYPE Kreis IS ABSTRACT NEW FlaechenobjektWITH PRIVATE;

 PRIVATE

TYPE Kreis IS ABSTRACT NEW FlaechenobjektWITHRECORD

Radius: Float;END RECORD;

 END Geo.Flaechenobjekte.Kreise;

-- Private Vereinbarung des Typs Rechteck im Paket-- Geo.Flaechenobjekte.Rechtecke PACKAGE Geo.Flaechenobjekte.Rechtecke IS

TYPE Rechteck IS ABSTRACT NEWFlaechenobjekt WITH PRIVATE;

 PRIVATE

TYPE Rechteck IS ABSTRACT NEWFlaechenobjekt WITH

RECORDEckpunkt_2: Pixel_Koordinaten;

END RECORD; END Geo.Flaechenobjekte.Rechtecke;

Paketstruktur

Geo 

Flaechenobjekte  

Kreise Rechtecke

TypstrukturGeometrisches_Objekt Farbe

Bezugspunkt  

Flaechenobjekt FarbeBezugspunktGefuellt

  

Kreis Farbe Rechteck FarbeBezugspunkt BezugspunktGefuellt GefuelltRadius Eckpunkt_2

Anwendung des Pakets Geo -- Ausgabe einer Reihung geometrischer ObjekteWITH Geo;PACKAGE Geo_Reihungen IS 

TYPE Geo_Zeiger IS ACCESS Geo.Geometrisches_Objekt´Class;

TYPE Geo_Reihung IS ARRAY (Positive RANGE <>) OF Geo_Zeiger; 

PROCEDURE Zeige (Was: IN Geo_Reihung); END Geo_Reihungen;

WITH Geo; USE Geo;PACKAGE BODY Geo_Reihungen IS 

PROCEDURE Zeige (Was: IN Geo_Reihung) ISBEGIN

FOR I IN Was´Range LOOPZeige (Was (I).ALL);

END LOOP;END Zeige;

 END Geo_Reihungen;

a parent

x

y

b parent c parent

y y

z z

Merkmalsobjekt Allgemeines Merkmalsobjekt  

parent clone+ print-

  a parent b parent c parent

y y yz z z

c n 

x 15 x 15y 4 c.clone n y 4m1 m1

  

x 15 n ADDS x 15n REMOVE y m1 VAR z z 10

10 z m1METHOD m2 … ; m2ENDADDS

 

Prototyp P P-Objekt P1  

Klasse P Eltern P-Objekt P2

  

 Kind Kind

   

Prototyp N Klasse N N-Objekt n 

Recommended