Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung -...

100

Transcript of Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung -...

Page 1: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Grundkonzepte

objektorientierter Programmierung -

Beispiele in

Java, Oberon-2, Python und Delphi

Projektarbeit im Studiengang Lehramt Informatik

Sommersemester 2006

Friedrich-Schiller-Universität Jena

erstellt vonNicole Himmerlich

betreut vonProf. Dr. Michael Fothe

&Lutz Kohl

August 2006

Page 2: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik
Page 3: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Inhaltsverzeichnis

1 Konzepte und Begri�e der Objektorientierung 1

2 Beispiel: Konto 32.1 Aggregierung und enge Kopplung . . . . . . . . . . . . . . . . . . . . . 32.2 Datenkapselung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.3 Konstruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.4 Klassen- und instanzspezi�sche Komponenten . . . . . . . . . . . . . . 142.5 Manipulierbarkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.6 Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202.7 Reimplementierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262.8 Polymorphismus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302.9 Überladen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

3 Beispiel: Mediendatenbank 35

4 Beispiel: Geometrische Figuren 48

A Python-Quellcode 61A.1 Beispiel: Konto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61A.2 Beispiel: Mediendatenbank . . . . . . . . . . . . . . . . . . . . . . . . . 67A.3 Beispiel: Geometrische Figuren . . . . . . . . . . . . . . . . . . . . . . 69

B Delphi-Quellcode 72B.1 Beispiel: Konto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72B.2 Beispiel: Mediendatenbank . . . . . . . . . . . . . . . . . . . . . . . . . 87B.3 Beispiel: Geometrische Figuren . . . . . . . . . . . . . . . . . . . . . . 91

Page 4: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik
Page 5: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

1 Konzepte und Begri�e der Objektorientierung

Die Prädicate der Erscheinung können dem Objecte selbst beigelegt werden,in Verhältniÿ auf unseren Sinn, z.B. der Rose die rothe Farbe, oder der Ge-ruch; [...]1 KantWie wir uns räumliche Gegenstände überhaupt nicht auÿerhalb der Zeitdenken können, so können wir uns keinen Gegenstand auÿerhalb der Mög-lichkeiten seiner Verbindung mit anderen denken.2 Wittgenstein

Die obigen Zitate zeigen, dass objektorientiertes Denken keine Er�ndung der Informa-tik ist, vielmehr gehen wir alle täglich mit Objekten um. �[Somit ist Objektorientierung]für uns Menschen eine natürliche Betrachtungsweise. Wir wissen, dass Objekte Eigen-schaften und ein Verhalten besitzen und aus anderen Objekten zusammengesetzt seinkönnen. Wir betrachten von einem Objekt nur gerade so viel, wie uns im Momentinteressiert und fassen gleichartige Objekte in Gruppen zusammen.�3

Die Informatik hat diese Betrachtungsweise aufgegri�en und zu einem Programmier-paradigma entwickelt.Der Begri� Objekt umfasst Gegenstände, Personen, Sachverhalte oder Ereignisse. Jedeseinzelne Objekt lässt sich durch drei Aspekte charakterisieren: es besitzt einen eindeu-tigen Zustand, ein wohlde�niertes Verhalten und eine Identität.Der Zustand eines Objektes repräsentiert alle seine relevanten Eigenschaften und istdurch eine Menge von Attributen und deren Werte bestimmt. Durch sie wird die Struk-tur der Objekte vereinbart. Die Attributmenge eines Objektes ändert sich normaler-weise nicht, die konkreten Werte sind jedoch veränderlich.Das Verhalten wird in der objektorientierten Programmierung durch eine Menge vonMethoden beschrieben. Sie bestimmen die Art und Weise, in der ein Objekt, in Ab-hängigkeit von seinem Zustand auf Einwirkungen reagiert, und können Attributwertemanipulieren.Die Identität eines Objektes ist diejenige Eigenschaft, die es von allen anderen Objek-ten unterscheidet. Sie stellt sicher, dass alle Objekte unterscheidbar sind, auch wenn siezufällig identische Attributwerte besitzen. Dabei muss gerade in der Softwareentwick-lung zwischen dem Namen eines Objektes und seiner Identität di�erenziert werden, dader Name der Adressierung dient und ein einzelnes Objekt über verschiedene Namenangesprochen werden kann.Objekte können nach bestimmten Kriterien gruppiert werden. Statt jedes Objekt ein-zeln zu beschreiben, werden gemeinsame Merkmale in Klassen zusammengefasst. Eine

1[Kan89, S.115, �8 Allgemeine Anmerkungen zur transzendentalen Ästhetik, Abschnitt iii]2[Wit66, S.12, Satz 2.0121]3[LS96, S.4]

1

Page 6: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Klasse ist somit eine abstrakte Beschreibung der Struktur und des Verhaltens vongleichartigen Objekten. Ein konkretes Objekt wird dann auch als Instanz einer Klassebezeichnet.Zu den Grundprinzipien der objektorientierten Programmierung gehören noch weitereKonzepte:

� Aggregierung

� Kopplung

� Kapselung und Information Hiding

� Konstruktoren und Destruktoren

� Instanz- und klassenspezi�sche Komponenten

� Vererbung

� Mehrfachvererbung

� Reimplementierung

� Polymorphismus

� Dynamisches Binden

� Abstrakte Klassen

� Generische Klassen

� Assoziation

� Aggregation

� Komposition

Einige dieser Konzepte werden im Folgenden anhand einfacher Beispiele näher erläu-tert. Auf eine ausführliche Darstellung der anderen Prinzipien wird verzichtet. Sie sindhier nur erwähnt, um die Vielfalt objektorientierter Programmierung zu verdeutlichen.Nicht alle vorgestellten Konzepte sind �rein objektorientiert�, objektorientierte Pro-grammierung wird viel mehr durch die Gesamtheit aller Konzepte geprägt. Dies be-deutet andererseits aber nicht, dass jede als objektorientiert bezeichnete Programmier-sprache auch alle Konzepte beinhaltet bzw. unterstützt.Der der Informatik-Lehrplan für Thüringen4 sieht vor, dass die Grundprinzipien des ob-jektorientierten Programmierens im Leistungskurs Informatik behandelt werden. Fürdie Umsetzung der Beispiele wurden deshalb Programmiersprachen5 gewählt, die anThüringer Schulen im Einsatz sind.

4Thüringer Kultusministerium (Hrsg.): Lehrplan für das Gymnasium - Informatik, 1999.5Java: Java 2 SDK 5.0; Oberon-2: POW!; Python: Python 2.4.3; ObjectPascal: Delphi 7.

2

Page 7: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

2 Beispiel: Konto

Zur näheren Erläuterung zentraler Eigenschaften objektorientierter Programmierungsoll zunächst ein Bankkonto schrittweise modelliert werden.Jedes Bankkonto besitzt üblicherweise eine eindeutige Kontonummer und einen ak-tuellen Kontostand. Natürlich sind noch weitere Kennzeichen - z.B. Kontoinhaber -denkbar. Sie werden jedoch zunächst vernachlässigt, damit die Quelltexte überschau-bar bleiben. Typische Aktionen, die auf einem Konto ausgeführt werden, sind das Ein-bzw. Auszahlen von Geldbeträgen und das Drucken eines Kontoauszugs.

2.1 Aggregierung und enge Kopplung

In der prozeduralen Programmierung werden zunächst die für die Beschreibung derDaten notwendigen Datenstrukturen gescha�en und danach werden die Funktionenentwickelt, mit deren Hilfe die Inhalte der vorhandenen Datenstrukturen ausgegebenbzw. manipuliert werden können. Obwohl sich die Funktionen auf die Datenstrukturenbeziehen, können Daten und Funktionen nicht als eine Einheit betrachtet werden. Ins-besondere wenn mehrere Datenstrukturen deklariert werden müssen, ist die Zuordnungder Funktionen nicht sofort ersichtlich.In der objektorientierten Programmierung werden zusammengehörige Attribute (Da-ten) und Methoden (Funktionen) zu einer manipulierbaren Gröÿe - einer Klasse - zu-sammengefasst. Sie bilden sozusagen ein Aggregat6, dessen Komponenten aufeinanderBezug nehmen können.In unserem Beispiel werden alle notwendigen Attribute und Methoden für ein Bank-konto in der Klasse Konto zusammengefasst, so dass sich das in Abb. 1 gezeigte Modellergibt. Die Methoden einzahlen(betrag) und auszahlen(betrag) verändern den Konto-

Abbildung 1: Klasse Konto

stand eines Bankkontos, d.h. sie müssen auf das Attribut saldo zugreifen und dessen6In der Literatur wird häu�g der Begri� Kapselung verwendet. Um Verwechselungen mit dem

Begri� Datenkapselung - im Sinne des Information Hiding - zu vermeiden, wird hier der Begri�Aggregierung (ein Aggregat bilden) benutzt.

3

Page 8: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Wert verändern. Die Methode auszug() bezieht sich sogar auf die beiden Attribute derKlasse, da sie kontonummer und saldo ausgibt. Daran zeigt sich die enge Kopplungzwischen Attributen und Methoden.

Java

In Java wird ein Klasse über das Schlüsselwort class de�niert. Alle Variablen, Funk-tionen bzw. Prozeduren, die innerhalb der geschweiften Klammern de�niert werden,gehören damit zur Klasse und bilden deren Attribute und Methoden. Innerhalb ei-ner Klasse können Attribute und Methoden direkt über ihren Namen angesprochenwerden. Eine Quelldatei sollte nur eine Klassende�nition enthalten und den gleichenNamen wie die Klasse tragen.

//Datei: Konto1/Konto.java//Beispiel : Aggregierung und Kopplung// −−> Aggregierungclass Konto{// Attributeint kontonummer;double saldo;// Methodenvoid einzahlen(double betrag){saldo = saldo + betrag; // −−> Kopplung

}void auszahlen(double betrag){saldo = saldo − betrag; // −−>Kopplung

}void auszug(){System.out.println("Kontonummer: "+kontonummer+" Saldo: "+saldo+" Euro");

}}

Java ist eine rein objektorientierte Sprache, so dass jedes Programm eine Klasse de�-niert. Deshalb wird das Testprogramm für die Klasse Konto in eine Klasse KontoTesteingebettet, die nur die Methode main enthält.Um von der Klasse Konto ein Objekt bzw. eine Instanz zu erzeugen, wird eine Variablevom Typ Konto deklariert. Der Operator new legt, mit Hilfe der vom Compiler er-zeugten Methode Konto(), ein neues Konto-Objekt an, das anschlieÿend der VariablenmeinKonto zugewiesen wird. Dabei gilt: Variablen, deren Typ eine Klasse ist, enthaltennicht das eigentliche Objekt, sondern nur einen Adressverweis auf dessen Speicherplatz.Insbesondere bedeutet dies, dass in meinKonto nur die Speicheradresse des Objektesabgelegt ist (siehe Abb. 2).Für den Zugri� auf Attribute oder Methoden eines Objektes wird eine Punktnota-tion verwendet. Attribute können mittels Referenz.Attribut gelesen und deren Werteverändert werden. Methoden werden durch Referenz.Methode() aufgerufen.

4

Page 9: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Abbildung 2: Objektreferenz

// Datei: Konto1/KontoTest.java// Beispiel : Aggregierung und Kopplungpublic class KontoTest{public static void main(String[] args){Konto meinKonto; // Variable vom Typ KontomeinKonto = new Konto(); // new erzeugt Instanz der Klasse KontomeinKonto.kontonummer = 4531088; // Zugri� auf AttributemeinKonto.saldo = 200.00;System.out.println("Kontonummer: "+meinKonto.kontonummer +" Saldo: "+ meinKonto.saldo);meinKonto.einzahlen(300.00); // MethodenaufrufmeinKonto.auszug();System.out.println ();Konto deinKonto = new Konto(); // deinKonto zeigt auf neue Instanz der Klasse KontodeinKonto.kontonummer = 1733065;deinKonto.saldo = 1000.00;deinKonto.auszug();deinKonto.auszahlen(100.00);deinKonto.auszug();

}}

Oberon-2

Oberon-2 verwendet sogenannte typgebundene Prozeduren, um die Zugehörigkeit derMethoden zur Klasse deutlich zu machen.Die Attribute einer Klasse werden als Felder eines Recordtyps dargestellt. Da Oberonnicht automatisch mit Referenzvariablen arbeitet, wird auÿerdem ein Referenztyp zumRecordtyp der Klasse de�niert.Die Implementierung der Methoden muss zusätzlich einen speziellen Parameter vordem Prozedurnamen besitzen. Dieser Parameter wird Empfänger genannt und reprä-sentiert das Objekt, für das die Methode aufgerufen wird. Der Typ des Empfängersgibt an, zu welcher Klasse die Methode gehört. Im Prozedurrumpf wird der Empfängergenutzt, um auf die Attribute der Klasse zuzugreifen. Dabei wird wieder die Punktno-tation (Empfänger.Attribut) angewendet.In Oberon-2 müssen zunächst alle Datentypen deklariert werden, bevor Prozedurenimplementiert werden können. Deshalb sollte jede Klasse in einem separaten Modulbeschrieben werden. Sind mehrere Klassende�nitionen in einem Modul enthalten, gehtschnell die Übersichtlichkeit verloren und es ist nicht mehr klar erkennbar, welche Me-thoden zu welchem Datentyp gehören.

5

Page 10: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

(* Datei: Konto1/Konto.mod *)(* Beispiel : Aggregierung und Kopplung *)MODULE Konto;IMPORT Out;TYPE

(* Attribute *)Konto* = RECORD

kontonummer* : LONGINT;saldo * : REAL

END;(* zugehoeriger Referenztyp *)KontoRef* = POINTER TO Konto;

(* Methoden *)(* −−> Aggregierung durch typgebundene Prozeduren*)PROCEDURE (k : KontoRef) einzahlen*(betrag : REAL);BEGINk.saldo := k.saldo + betrag; (* −−> Kopplung *)

END einzahlen;PROCEDURE (k : KontoRef) auszahlen*(betrag : REAL);BEGINk.saldo := k.saldo − betrag; (* −−> Kopplung *)

END auszahlen;PROCEDURE (k : KontoRef) auszug*();BEGINOut.String("Kontonummer: ");Out.Int(k.kontonummer, 10);Out.String(" Saldo: ");Out.Real(k.saldo , 10);Out.String(" Euro");Out.Ln;

END auszug;BEGINEND Konto.

Um eine Instanz der Klasse Konto zu erzeugen, wird eine Variable vom Typ KontoRefdeklariert. Der Aufruf NEW(meinKonto) legt ein Objekt vom Typ Konto an, d.h. erstellt entsprechenden Speicherplatz zur Verfügung. Zudem bewirkt er, dass meinKontoauf dieses Objekt verweist. Über die Variable meinKonto können die Attribute derInstanz angesprochen werden (meinKonto.Attribut). Für den Aufruf von Methodenwird ebenfalls die Punktnotation (meinKonto.Methode()) verwendet.

(* Datei: Konto1/KontoTest.mod *)(* Beispiel : Aggregierung und Kopplung *)MODULE KontoTest;IMPORT Konto, Out;PROCEDURE ProgMain*();VAR meinKonto, deinKonto : Konto.KontoRef; (* Variablen vom Referenztyp Konto *)BEGIN

NEW(meinKonto); (* NEW erzeugt Instanz der Klasse Konto *)

6

Page 11: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

meinKonto.kontonummer := 4531088; (* Zugri� auf Attribute *)meinKonto.saldo := 200.00;Out.String("Kontonummer: ");Out.Int(meinKonto.kontonummer, 10);Out.String(" Saldo: ");Out.Real(meinKonto.saldo, 10);Out.Ln;meinKonto.einzahlen(300.00); (* Methodenaufruf *)meinKonto.auszug();Out.Ln;NEW(deinKonto); (* deinKonto zeigt auf neue Instanz der Klasse Konto *)deinKonto.kontonummer := 1733065;deinKonto.saldo := 1000.00;deinKonto.auszug();deinKonto.auszahlen(100.00);deinKonto.auszug();

END ProgMain;BEGINEND KontoTest.

2.2 Datenkapselung

Das Prinzip der Datenkapselung wurde bereits 1972 von David Parnas propagiert7. Erprägte damals den Begri� Information Hiding. Im Deutschen wird oft die BezeichnungGeheimnisprinzip verwendet.Für den Benutzer einer Klasse ist relevant, wie er eine Komponente verwenden kann,nicht wie sie realisiert ist. Deshalb wird die Struktur eines Objektes und die Implemen-tierung der Methoden nicht o�en gelegt, sondern in der Klasse verborgen. Der Zugri�auf die gekapselten Attribute und deren Manipulation ist dann ausschlieÿlich über dieMethoden der Klasse durchführbar. So wird sichergestellt, dass Attributwerte nichtwillkürlich geändert und nur zulässige Werte gespeichert werden.Das Verstecken der Implementierungsdetails vermindert die Fehleranfälligkeit, da einunerwarteter Zugri� unmöglich ist. Änderungen der Implementierung haben keine Aus-wirkung auf den Nutzer, da dieser die Zugri�smethoden weiterhin verwenden kann.Im Fall der Klasse Konto sollen die Attribute kontonummer und saldo vor unkon-trolliertem Zugri� geschützt werden. Da das Lesen und Verändern der Attribute aberzunächst noch möglich sein soll, werden neue Methoden benötigt. Die Methoden get-Kontonummer() und setKontonummer(nummer) ermöglichen Lese- und Schreibzugri�auf das Attribut kontonummer. Für die Manipulation von saldo wurden die Operatio-nen getSaldo() und setSaldo(betrag) de�niert.

7Das Konzept der Datenkapselung ist ein wichtiges Prinzip der Informatik, das nicht nur in derobjektorientierten Programmierung eingesetzt wird.

7

Page 12: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Java

Die Zugri�srechte werden in Java über sogenannte Modi�zierer festgelegt.Wird ein Attribut ohne Zusatz deklariert, so ist es in allen Klassen des deklarierendenPaketes8 sichtbar, nicht jedoch in anderen Paketen. Das Schlüsselwort public erlaubtlesenden und schreibenden Zugri�, d.h. die Attribute sind in allen Paketen sichtbar.Sollen Attribute nur innerhalb der Klasse sichtbar sein, so müssen sie mit dem Modi-�zierer private gekennzeichnet werden.Da die Attribute kontonummer und saldo versteckt werden sollen, sind sie ab sofortmit dem Vorsatz private versehen.Modi�zierer regeln auch die Sichtbarkeit von Methoden. Da die Methoden der KlasseKonto in jedem Paket zugänglich sein sollen, müssen sie als public deklariert werden.Das Schlüsselwort public kann auch auf Klassen angewendet werden. Klassen, die mitpublic gekennzeichnet sind, können überall benutzt werden. In einer Quelldatei darfjedoch höchstens eine Klasse als public deklariert werden.

//Datei: Konto2/Konto.java//Beispiel : Datenkapselungpublic class Konto{private int kontonummer; // −−> Datenkapselungprivate double saldo;// neue Methoden fuer sicheren Zugri� auf Attribut kontonummerpublic int getKontonummer(){return kontonummer;

}public void setKontonummer(int nummer){kontonummer = nummer;

}// neue Methoden fuer sicheren Zugri� auf Attribut saldopublic double getSaldo(){return saldo;

}public void setSaldo(double betrag){saldo = betrag;

}// urspruengliche Methodenpublic void einzahlen(double betrag){saldo = saldo + betrag;

}public void auszahlen(double betrag){saldo = saldo − betrag;

}public void auszug(){System.out.println("Kontonummer: "+kontonummer+" Saldo: "+saldo+" Euro");

}}

8Pakete bestehen aus mehreren Klasse, die zu einer gröÿeren Einheit zusammengefasst werden.Um eine Klasse einem bestimmten Paket zuzuordnen muss die Anweisung package Paketname; alserste Anweisung im Quellcode stehen.

8

Page 13: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Auÿerhalb der Klasse Konto ist ein direkter Zugri� auf die Attribute kontonummerund saldo nicht mehr möglich. Der Befehl meinKonto.kontonummer = 4531088 führtzu einem Fehler bei der Übersetzung. Sogar der Versuch lesend auf die Variable zu-zugreifen, erzeugt eine Fehlermeldung. Die Attribute können nur über entsprechendeMethoden angesprochen werden.

//Datei: Konto2/KontoTest.java//Beispiel : Datenkapselungpublic class KontoTest{public static void main(String[] args){Konto meinKonto = new Konto();

/* meinKonto.kontonummer = 4531088; !! FehlerSystem.out.println(meinKonto.kontonummer); !! Fehler */meinKonto.setKontonummer(4531088); // schreibender Zugri� auf Attribute ueber entsprechende MethodenmeinKonto.setSaldo(200.00);System.out.print("Kontonummer: "+meinKonto.getKontonummer()); // lesender Zugri�System.out.println(" Saldo: "+meinKonto.getSaldo()+" Euro");

}}

Oberon-2

In Oberon-2 werden Attribute und Methoden nur dann exportiert, wenn sie in ihrerDeklaration mit einem Stern (*) markiert sind. Wird die Markierung weggelassen, sosind die Namen nur innerhalb des Moduls sichtbar, in der die Klasse implementiertwird. Andere Module, die das Modul importieren, können nur auf die exportiertenAttribute und Methoden zugreifen.In der KlasseKonto wird der Stern an den Attributen kontonummer und saldo entfernt.Der Name des Record, der zugehörige Referenztyp und die Methoden sollen weiterhinsichtbar sein und behalten deshalb ihre Markierung.

(* Datei: Konto2/Konto.mod *)(* Beispiel : Datenkapselung *)MODULE Konto;IMPORT Out;TYPEKonto* = RECORD

kontonummer : LONGINT; (* −−> Datenkapselung *)saldo : REAL

END;KontoRef* = POINTER TO Konto;

(* neue Methoden fuer sicheren Zugri� auf Atrribut kontonummer *)PROCEDURE (k : KontoRef) getKontonummer*() : LONGINT;BEGINRETURN k.kontonummer;

END getKontonummer;PROCEDURE (k : KontoRef) setKontonummer*(nummer : LONGINT);BEGINk.kontonummer := nummer;

END setKontonummer;

9

Page 14: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

(* neue Methoden fuer sicheren Zugri� auf Atrribut saldo *)PROCEDURE (k : KontoRef) getSaldo*() : REAL;BEGINRETURN k.saldo;

END getSaldo;PROCEDURE (k : KontoRef) setSaldo*(betrag : REAL);BEGINk.saldo := k.saldo + betrag;

END setSaldo;(* urspruengliche Methoden *)PROCEDURE (k : KontoRef) einzahlen*(betrag : REAL);BEGINk.saldo := k.saldo + betrag;

END einzahlen;PROCEDURE (k : KontoRef) auszahlen*(betrag : REAL);BEGINk.saldo := k.saldo − betrag;

END auszahlen;PROCEDURE (k : KontoRef) auszug*();BEGINOut.String("Kontonummer: ");Out.Int(k.kontonummer, 10);Out.String(" Saldo: ");Out.Real(k.saldo , 10);Out.String(" Euro");Out.Ln;

END auszug;BEGINEND Konto.

Die Namen kontonummer und saldo werden vom Modul Konto nicht mehr exportiert.Die Verwendung dieser Namen im Modul KontoTest führt deshalb zu der Fehlermel-dung �Error 83: unde�ned record �eld�. Um die Attribute trotzdem zu bearbeiten,benutzt man die set- und get-Methoden.

(* Datei: Konto2/KontoTest.mod *)(* Beispiel : Datenkapselung *)MODULE KontoTest;IMPORT Konto, Out;PROCEDURE ProgMain*();VAR meinKonto : Konto.KontoRef;BEGIN

NEW(meinKonto);(* meinKonto.kontonummer = 4531088; !! Fehler

Out.Int(meinKonto.kontonummer); !! Fehler *)meinKonto.setKontonummer(4531088); (* schreibender Zugri� auf Attribute ueber entsprechende Methoden *)meinKonto.setSaldo(200.00);Out.String("Kontonummer: ");Out.Int(meinKonto.getKontonummer(),10); (* lesender Zugri� *)Out.String(" Saldo: ");Out.Real(meinKonto.getSaldo(),10);Out.String(" Euro");

END ProgMain;

10

Page 15: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

BEGINOut.Open

END KontoTest.

2.3 Konstruktor

Konstruktoren sind spezielle Methoden einer Klasse, die immer dann zum Einsatz kom-men, wenn ein neues Objekt erzeugt werden soll. Sie sind eine elegante Möglichkeit,Objekte zu initialisieren, können aber auch individuelles Verhalten implementieren.Die Klasse Konto erhält einen Konstruktor, der als Parameter eine Nummer überge-ben bekommt. Diese Nummer dient dem Konstruktor als Initialwert für das Attributkontonummer. Die Methode setKontonummer(nummer) wird gelöscht, da eine Kon-tonummer einmalig bei der Erö�nung des Kontos vergeben wird. Der Wert von saldowird durch den Konstruktor auf 0.00 gesetzt. Änderungen des Kontostandes sollenanschlieÿend nur über die Methoden einzahlen(betrag) und auszahlen(betrag) möglichsein, weshalb setSaldo(betrag) entfernt wird.

Java

In Java ist der Konstruktor eine Methode, die den gleichen Namen, wie die zugehörigeKlasse trägt. Er unterscheidet sich bei der De�nition von anderen Methoden dadurch,dass kein Objekttyp für die Rückgabe spezi�ziert werden darf.Der Konstruktor wird bei der Erzeugung eines Objektes nach dem Operator new auf-gerufen. Ein expliziter Aufruf der Form: Referenz.Konstuktor() ist nicht möglich.Ist für eine Klasse kein Konstruktor explizit deklariert, dann baut der Compiler einenStandardkonstruktor ohne Parameter ein. Dieser Konstruktor initialisiert alle Attribu-te mit NULL.

//Datei: Konto3/Konto.java//Beispiel : Konstruktorpublic class Konto{private int kontonummer;private double saldo;// −−> Konstruktorpublic Konto(int nummer){kontonummer = nummer;saldo = 0.0;

}public int getKontonummer(){return kontonummer;

}// setKontonummer(nummer) entfernt

11

Page 16: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

public double getSaldo(){return saldo;

}// setSaldo(betrag) entferntpublic void einzahlen(double betrag){saldo = saldo + betrag;

}public void auszahlen(double betrag){saldo = saldo − betrag;

}public void auszug(){System.out.println("Kontonummer: "+kontonummer+" Saldo: "+saldo+" Euro");

}}

Bisher wurden die Instanzen der Klasse Konto mit dem Standardkonstruktor Konto()erstellt. Dieser wird jetzt durch den neuen Konstruktor Konto(nummer) ersetzt. Erübernimmt die Initialisierung der Attribute, so dass dies nicht mehr explizit gesetztwerden müssen.

//Datei: Konto3/Konto.java//Beispiel : Konstruktorpublic class KontoTest{public static void main(String[] args){Konto meinKonto;

/* bisher :meinKonto = new Konto(); // Objekt erzeugenmeinKonto.setKontonummer(4531088); // Kontonummer initialisierenmeinKonto.setSaldo(0.00); // Kontostand initialisieren */

/* jetzt : */meinKonto = new Konto(4531088); // Konstruktor erzeugt Objekt und initialisiert AttributemeinKonto.auszug();

}}

Oberon-2

Im Sprachkonzept von Oberon-2 sind Konstruktoren nicht enthalten. Sie können aberdurch entsprechend implementierte Methoden nachgebaut werden.Im Beispiel der Klasse Konto wurde eine Methode Konto(nummer) de�niert, die alsKonstruktor verwendet wird. Diese Methode ist verantwortlich für die Initialisierungder Attribute kontonummer und saldo.

(* Datei: Konto3/Konto.mod *)(* Beispiel : Konstruktor *)MODULE Konto;IMPORT Out;

12

Page 17: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

TYPEKonto* = RECORD

kontonummer : LONGINT;saldo : REAL

END;KontoRef* = POINTER TO Konto;

(* −−> Konstruktor *)PROCEDURE (k : KontoRef) Konto*(nummer : LONGINT);BEGINk.kontonummer := nummer;k.saldo := 0.0;

END Konto;PROCEDURE (k : KontoRef) getKontonummer*() : LONGINT;BEGINRETURN k.kontonummer;

END getKontonummer;(* setKontonummer(nummer) entfernt *)PROCEDURE (k : KontoRef) getSaldo*() : REAL;BEGINRETURN k.saldo;

END getSaldo;(* setSaldo(betrag) entfernt *)PROCEDURE (k : KontoRef) einzahlen*(betrag : REAL);BEGINk.saldo := k.saldo + betrag;

END einzahlen;PROCEDURE (k : KontoRef) auszahlen*(betrag : REAL);BEGINk.saldo := k.saldo − betrag;

END auszahlen;PROCEDURE (k : KontoRef) auszug*();BEGINOut.String("Kontonummer: ");Out.Int(k.kontonummer, 10);Out.String(" Saldo: ");Out.Real(k.saldo , 10);Out.String(" Euro");Out.Ln;

END auszug;BEGINEND Konto.

Instanzen einer Klasse werden weiterhin durch den Operator NEW erzeugt. Die Me-thode Konto(nummer) initialisiert lediglich die Attribute. Da Konto(nummer) einenormale Methode ist, kann sie - im Gegensatz zu Konstruktoren in Java - uneinge-schränkt genutzt und mittels Referenz.Konto(nummer) aufgerufen werden. Der Pro-grammierer muss selbst darauf achten, dass sie nur nach der Generierung eines neuenObjektes verwendet wird, da sie sonst eventuell die Daten eines bereits bestehendenObjektes überschreibt.9

9Eine weitere Variante der Konstruktormethode für Oberon-2-Programme, die den NEW-Operatorbeinhaltet, wird in den Beispielen Mediendatenbank und geometrische Figuren vorgestellt.

13

Page 18: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

(* Datei: Konto3/KontoTest.mod *)(* Beispiel : Konstruktor*)MODULE KontoTest;IMPORT Konto, Out;PROCEDURE ProgMain*();VAR meinKonto : Konto.KontoRef;BEGIN

NEW(meinKonto); (* Objekt erzeugen *)(* bisher :

meinKonto.setKontonummer(4531088); // Kontonummer initialisierenmeinKonto.setSaldo(0.00); // Kontostand initialisieren *)

(* jetzt : *)meinKonto.Konto(4531088); (* Konstruktor initialisiert Attribute *)meinKonto.auszug;

END ProgMain;BEGIN

Out.OpenEND KontoTest.

2.4 Klassen- und instanzspezi�sche Komponenten

Für Klassen können statische Variablen und Methoden de�niert werden. Das Besonde-re an diesen Komponenten ist, dass sie nicht auf die Existenz von Instanzen der Klasseangewiesen sind.Von Klassenvariablen existiert, unabhängig von der Anzahl der Instanzen, nur einExemplar, das von allen Objekten der Klasse gemeinsam genutzt wird. Sie werdenbeim Laden der Klasse erzeugt und erst freigegeben, wenn das Programm endet. Wäh-rend der Zugri� auf Instanzvariablen durch den Befehl Instanz.Variablenname erfolgt,werden klassenspezi�sche Variablen in der Form: Klassenname.Variablenname ange-sprochen. Wenn ein Attribut für alle Instanzen einer Klasse den gleichen Wert habensoll, ist die Verwendung von Klassenvariablen angebracht. Anstatt den Wert in jedemeinzelnen Objekt anzulegen, wird er in der Klasse gespeichert.Klassenmethoden werden eingesetzt um Verhalten zu implementieren, dass für alleInstanzen einer Klasse gleich ist. Man muss jedoch darauf achten, dass sie nicht auf In-stanzvariablen zugreifen oder Instanzmethoden aufrufen, da sie auch aufgerufen werdendürfen, wenn keine Instanz existiert. Zudem wäre in solch einer Situation nicht ein-deutig festgelegt, welche Instanz verwendet werden muss. Klassenmethoden werden -genau wie Klassenvariablen - über den Name der Klasse aufgerufen.Die Klasse Konto könnte zum Beispiel einen Instanzenzähler enthalten, der festhält,wie viele Objekte vom Typ Konto erzeugt wurden. Der Wert der Variablen muss alsoimmer dann um 1 erhöht werden, wenn ein neues Objekt angelegt wird. Deshalb sollte

14

Page 19: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

die entsprechende Anweisung im Konstruktor implementiert werden. Zu Beginn derProgramm-Abarbeitung steht der Zähler auf 0, da noch keine Instanz existiert.

Java

Klassenvariablen und -methoden werden in Java durch das Schlüsselwort static ge-kennzeichnet.Im Beispiel der Klasse Konto wird das Attribut zaehler durch den Vorsatz static zueiner Klassenvariablen. Unabhängig von der Anzahl der Konto-Objekte existiert nurein Exemplar dieser Variablen. Die Attribute kontonummer und saldo sind Instanzva-riablen. Sie werden für jede Instanz der Klasse Konto neu angelegt (siehe Abb.3).

Abbildung 3: Instanz- und Klassenvariablen

//Datei: Konto4/Konto.java//Beispiel : Klassen− und Instanzvariablenpublic class Konto{static int zaehler = 0; // −−> Klassenvariableprivate int kontonummer; // −−> Instanzvariablenprivate double saldo;public Konto(int nummer){zaehler = zaehler + 1;kontonummer = nummer;saldo = 0.00;

}public int getKontonummer(){return kontonummer;

}

15

Page 20: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

public double getSaldo(){return saldo;

}public void einzahlen(double betrag){saldo = saldo + betrag;

}public void auszahlen(double betrag){saldo = saldo − betrag;

}public void auszug(){System.out.println("Kontonummer: "+kontonummer+" Saldo: "+saldo+" Euro");

}}

Für die Variable zaehler wird beim Laden der Klasse Konto Speicherplatz belegt, dermit 0 vorinitialisiert ist. Nachdem durch den Konstruktor eine Instanz erzeugt wurde,ist der Wert von zaehler 1. Das Anlegen einer weiteren Instanz bewirkt eine erneuteErhöhung.

// Datei: Konto4/KontoTest.java// Beispiel : Klassenvariablenpublic class KontoTest{public static void main(String[] args){// Zugri� auf Klassenvariablen ueber KlassennamenSystem.out.println("Anzahl Konten: "+Konto.zaehler);Konto meinKonto = new Konto(4531088);System.out.println("Anzahl Konten: "+Konto.zaehler);Konto deinKonto = new Konto(1733065);System.out.println("Anzahl Konten: "+Konto.zaehler);

}}

Oberon-2

In Oberon-2 gibt es keine statischen Komponenten im eigentlichen Sinne. Die Daten-felder des Recordtyps sind Instanzvariablen und werden für jedes Objekt neu angelegt.Klassenvariablen können somit nicht im Record deklariert werden. Stattdessen werdensie im Variablendeklarationsteil des Moduls de�niert. Man muss jedoch beachten, dassdiese Variablen nicht an eine Klasse gebunden sind. Viel mehr sind es Modulvariablen,die von auÿen mittels Modulname.Variablenname angesprochen werden. Dies ist ins-besondere dann wichtig, wenn der Klassenname von Namen des Moduls abweicht odermehrere Klassen in einem Modul implementiert sind.Ähnliches gilt für Methoden. Instanzmethoden werden durch einen Empfängerpara-meter dem Recordtyp zugeordnet. Wird dieser Parameter weggelassen, so sind dieProzeduren statisch. Sie können in Modulen, über den Modulnamen aufgerufen wer-den.

16

Page 21: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

In unserem Beispiel wird im Modul Konto eine Integer-Variable zaehler deklariert.Der Konstruktor der Klasse Konto verwendet diese Variable, um die Anzahl der In-stanzen zu zählen. Um auf den Wert der Variable zuzugreifen, genügt innerhalb desdeklarierenden Moduls der Variablenname.

(* Datei: Konto4/Konto.mod *)(* Beispiel : Klassen− und Instanzvariablen *)MODULE Konto;IMPORT Out;TYPEKonto* = RECORD

kontonummer : LONGINT; (* −−> Instanzvariablen *)saldo : REAL

END;KontoRef* = POINTER TO Konto;

(* −−> Modulvariable, ersetzt Klassenvariable *)VAR zaehler* : INTEGER;PROCEDURE (k : KontoRef) Konto*(nummer : LONGINT);BEGINzaehler := zaehler + 1;k.kontonummer := nummer;k.saldo := 0.0;

END Konto;PROCEDURE (k : KontoRef) getKontonummer*() : LONGINT;BEGINRETURN k.kontonummer;

END getKontonummer;PROCEDURE (k : KontoRef) getSaldo*() : REAL;BEGINRETURN k.saldo;

END getSaldo;PROCEDURE (k : KontoRef) einzahlen*(betrag : REAL);BEGINk.saldo := k.saldo + betrag;

END einzahlen;PROCEDURE (k : KontoRef) auszahlen*(betrag : REAL);BEGINk.saldo := k.saldo − betrag;

END auszahlen;PROCEDURE (k : KontoRef) auszug*();BEGINOut.String("Kontonummer: ");Out.Int(k.kontonummer, 10);Out.String(" Saldo: ");Out.Real(k.saldo , 10);Out.String(" Euro");Out.Ln;

END auszug;

BEGINzaehler := 0;

END Konto.

17

Page 22: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

(* Datei: Konto4/KontoTest.mod *)(* Beispiel : Klassen− und Instanzvariablen*)MODULE KontoTest;IMPORT Konto, Out;PROCEDURE ProgMain*();VAR meinKonto, deinKonto : Konto.KontoRef;BEGIN

Out.String("Anzahl Konten: ");(* Zugri� auf Klassenvariablen ueber Modulnamen *)Out.Int(Konto.zaehler,2);Out.Ln;NEW(meinKonto);meinKonto.Konto(4531088);Out.String("Anzahl Konten: ");Out.Int(Konto.zaehler,2);Out.Ln;NEW(deinKonto);meinKonto.Konto(1733065);Out.String("Anzahl Konten: ");Out.Int(Konto.zaehler,2);

END ProgMain;BEGIN

Out.OpenEND KontoTest.

2.5 Manipulierbarkeit

Instanzen einer Klasse können wie andere Werte manipuliert werden. Dazu gehört unteranderem, dass sie einer anderen Referenzvariable vom selben Typ zugewiesen werdenkönnen. Im Programmbeispiel werden drei Referenzvariablen angelegt, aber nur zweiInstanzen erzeugt. Die Zuweisung sorgt dafür, dass die beiden Variablen meinKontound unserKonto auf dasselbe Objekt verweisen, während deinKonto die zweite Instanzreferenziert (siehe Abb. 4).Auÿerdem können Objekte auf Gleichheit und Ungleichheit getestet werden. Wichtigist dabei, dass nur Zeigervergleiche und keine Wertvergleiche statt�nden. Obwohl dieKontonummer und der Kontostand von meinKonto und deinKonto identisch sind, lie-fert der Vergleich den Wert FALSE. Nur der Vergleich von deinKonto und unserKontoergibt TRUE.

Abbildung 4: Zuweisung und Vergleich von Objekten

18

Page 23: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Es ist möglich Prozeduren oder Funktionen zu de�nieren, die Klasseninstanzen als Pa-rameter haben. Für die Klasse Konto wurde eine Prozedur ueberweisen implementiert,die als Argumente zwei Konto-Objekte nimmt und einen vorgegebenen Betrag voneinem auf das andere überweist.

Java

//Datei: Konto5/Konto.java//Beispiel : Manipulierbarkeitpublic class KontoTest{static void ueberweisen(double betrag, Konto kontoA, Konto kontoZ){kontoA.auszug();kontoZ.auszug();kontoA.auszahlen(betrag);kontoZ.einzahlen(betrag);System.out.print("Von Konto "+kontoA.getKontonummer());System.out.print(" wurden "+betrag+" Euro ");System.out.println("auf Konto "+kontoZ.getKontonummer()+" ueberwiesen.");kontoA.auszug();kontoZ.auszug();

}public static void main(String[] args){Konto meinKonto = new Konto(4531088);meinKonto.einzahlen(300.00);Konto deinKonto = new Konto(4531088);deinKonto.einzahlen(300.00);Konto unserKonto;// ZuweisungunserKonto=deinKonto;// Vergleichif (meinKonto == deinKonto)

System.out.println("Mein Konto und dein Konto sind identisch.");elseSystem.out.println("Mein Konto und dein Konto sind verschieden.");

if (unserKonto == deinKonto)System.out.println("Unser Konto und dein Konto sind identisch.");

elseSystem.out.println("Unser Konto und dein Konto sind verschieden.");

// Parameterueberweisen(30.00, meinKonto, deinKonto);

}}

Oberon-2

(* Datei: Konto5/KontoTest.mod *)(* Beispiel : Manipulierbarkeit*)MODULE KontoTest;IMPORT Konto,Out;PROCEDURE ueberweisen(betrag : REAL; kontoA, kontoZ : Konto.KontoRef);BEGINkontoA.auszug();

19

Page 24: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

kontoZ.auszug();kontoA.auszahlen(betrag);kontoZ.einzahlen(betrag);Out.String("Von Konto ");Out.Int(kontoA.getKontonummer(),10);Out.String(" wurden ");Out.Real(betrag,10);Out.String(" Euro auf Konto ");Out.Int(kontoZ.getKontonummer(),10);Out.String(" ueberwiesen."); Out.Ln;kontoA.auszug();kontoZ.auszug();

END ueberweisen;PROCEDURE ProgMain*();VAR meinKonto, deinKonto, unserKonto : Konto.KontoRef;BEGIN

NEW(meinKonto);meinKonto.Konto(4531088);meinKonto.einzahlen(300.00);NEW(deinKonto);deinKonto.Konto(1733065);deinKonto.einzahlen(100.00);(* Zuweisung *)unserKonto := deinKonto;(* Vergleich *)IF meinKonto = deinKontoTHEN Out.String("Mein Konto und dein Konto sind identisch."); Out.Ln;ELSE Out.String("Mein Konto und dein Konto sind verschieden."); Out.Ln;END;IF unserKonto = deinKontoTHEN Out.String("Unser Konto und dein Konto sind identisch."); Out.Ln;ELSE Out.String("Unser Konto und dein Konto sind verschieden."); Out.Ln;END;(* Parameter *)ueberweisen(30.00, meinKonto, deinKonto);

END ProgMain;BEGIN

Out.OpenEND KontoTest.

2.6 Vererbung

Oft modellieren Klassen Dinge der realen Welt, die zwar in verschiedenen Variantenvorkommen, aber auch grundlegende Gemeinsamkeiten haben. In einer Bank gibt esz.B. verschiedene Kontoarten. Ein Sparkonto ist ein Konto mit Kontonummer undKontostand; zusätzlich zum normalen Konto werden jedoch Zinsen auf das Guthabengezahlt. Auÿerdem gibt es noch Girokonten, die über ein bestimmtes Kreditlimit ver-fügen. Für beide Konten sind das Einzahlen und Auszahlen von Geldbeträgen sowiedas Drucken eines Kontoauszuges typische Handlungen.Diese Methoden sind bereits in der Klasse Konto implementiert und können durch Ko-pieren in die Klassen Sparkonto und Girokonto übernommen werden. Damit müssen

20

Page 25: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

jedoch drei Versionen des selben Algorithmus gep�egt werden. Eine Möglichkeit, dieseCode-Duplizierung zu vermeiden, ist Vererbung.Vererbung ist eines der mächtigsten und interessantesten Konzepte des objektorien-tierten Programmierens. Sie ermöglicht, dass neue Klassen auf bereits vorhandenenKlassen und deren Funktionalität aufbauen.Haben mehrere Klassen gleiche Eigenschaften, so werden diese in einer Superklassezusammengefasst. Wird von dieser Klasse eine Subklasse abgeleitet, so erbt sie alleKomponenten der übergeordneten Klasse, d.h. Attribute und Methoden werden auto-matisch übernommen und müssen nicht erneut implementiert werden. Die Subklassekann anschlieÿend die für sie relevanten Attribute und Methoden hinzufügen.Auf diese Art und Weise ist es möglich, hierarchische Beziehungen zwischen einzelnenKlassen herzustellen. So können z.B. mehrere Klassen von einer Superklasse erben undeine Subklasse kann wiederum selbst Superklasse weiterer Subklassen sein.Von der Klasse Konto soll zunächst nur die Klasse Sparkonto abgeleitet werden. Dieseerbt die Attribute kontonummer und saldo, benötigt aber noch ein weiteres Attributzinssatz, in dem festgehalten wird, wieviel Prozent Zinsen gezahlt werden. Auf das At-tribut kann über die Methoden getZinssatz() und setZinssatz(zins) zugegri�en werden.Für die Buchung der Zinsen auf das jeweilige Konto wird eine zusätzliche Methodeverzinsen() implementiert. Alle weiteren Methoden werden von der Superklasse über-nommen. Insgesamt ergibt sich damit das in Abb. 5 dargestellte Klassendiagramm.

Abbildung 5: Vererbung

Java

Um in Java eine neue Klasse aus einer bestehenden abzuleiten, wird im Kopf der Klas-senbeschreibung das Schlüsselwort extends zusammen mit dem Namen der Super-klasse verwendet. Die Superklasse gibt dann die Variablen und Methoden, die publicoder protected deklariert sind, an die abgeleiteten Klassen weiter. Komponenten, die

21

Page 26: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

als private eingestuft sind, werden nicht vererbt. Sollen Attribute oder Methoden fürandere Klassen nicht sichtbar sein, aber trotzdem an die Subklasse vererbt werden,so müssen sie mit dem Schlüsselwort protected gekennzeichnet sein.10 Deshalb ändertsich der Modi�zierer der Attribute kontonummer und saldo von private in protected.Die Methoden der Klasse Konto behalten den Zusatz public, damit sie auch für andereKlassen sichtbar sind.

//Datei: Konto6/Konto.java//Beispiel : Vererbungpublic class Konto{static int zaehler = 0;protected int kontonummer; // Attribute sollen vererbt werdenprotected double saldo;

public Konto(int nummer){zaehler = zaehler + 1;kontonummer = nummer;saldo = 0.00;

}// Implementierung der Methoden hier ausgelassenpublic int getKontonummer(){}public double getSaldo(){}public void einzahlen(double betrag){}public void auszahlen(double betrag){}public void auszug(){}

}

Die Klasse Sparkonto wird durch extends von der Klasse Konto abgeleitet. Dadurcherbt sie alle Eigenschaften der übergeordneten Klasse und kann diese im Programm-code verwenden. Alle Deklarationen die im Rumpf der Klasse gemacht werden, sindErweiterungen von Konto.Konstruktoren werden nicht vererbt, aus diesem Grund benötigt die Klasse Sparkontoeinen eigenen Konstuktor Sparkonto(nummer, zins). In diesem wird mit dem Befehlsuper(nummer) zunächst der Konstruktor der Superklasse aufgerufen, d.h. alle An-weisungen von Konto(nummer) werden ausgeführt. Anschlieÿend muss nur noch dasneue Attribut zinssatz initialisiert werden.Die Methode verzinsen() ändert den Kontostand der aufrufenden Instanz. Obwohl dasAttribut saldo nicht in der Klasse Sparkonto deklariert worden ist, kann der Nameverwendet werden.

//Datei: Konto6/Sparkonto.java//Beispiel : Vererbung// −−> Vererbungpublic class Sparkonto extends Konto{private double zinssatz; // zusaetzliches Attribut10Komponenten für die kein Modi�zierer angegeben ist, werden nur innnerhalb eines Paketes an

Subklassen vererbt.

22

Page 27: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

// Konstuktor der Klasse Sparkontopublic Sparkonto(int nummer, double zins){super(nummer); // Konstruktor der Superklasse Konto wird aufgerufenzinssatz = zins;

}// neue Methoden fuer Zugri� auf Attribut zinssatzpublic double getZinssatz(){return zinssatz;

}public void setZinssatz(double zins){

zinssatz = zins;}// neue Methodepublic void verzinsen(){

saldo = saldo + (zinssatz*saldo)/100; // verwendet geerbte Attribute}

}

Eine Instanz der Klasse Sparkonto wird durch den Konstruktor Sparkonto(nummer,zins)erzeugt und initialisiert. Jedes Objekt vom Typ Sparkonto besitzt die drei Attributekontonummer, saldo und zinssatz, die mit Hilfe der Methoden getKontonummer(),getSaldo() und getZinssatz() ausgelesen werden können. Das Datenfeld zinssatz kanndurch die Methode setZinssatz(zins) beschrieben werden.Alle Methoden, die für eine Instanz der KlasseKonto de�niert sind, können auch auf einObjekt vom Typ Sparkonto angewendet werden. Dazu gehören die Methoden einzah-len(betrag), auszahlen(betrag) und auszug(). Zusätzlich verfügt jedes Sparkonto-Objektüber die Methode verzinsen().

//Datei: Konto6/KontoTest.java//Beispiel : Vererbungpublic class KontoTest{public static void main(String[] args){Sparkonto meinSparkonto = new Sparkonto(5613990,3.4);// jede Instanz der Klasse Sparkonto hat 3 AttributeSystem.out.print("Kontonummer: "+meinSparkonto.getKontonummer()); // geerbtes AttributSystem.out.print(" Saldo: "+meinSparkonto.getSaldo()+" Euro"); //geerbtes AttributSystem.out.println(" Zinssatz: "+meinSparkonto.getZinssatz()); // neu deklariertes Attribut// Methoden einzahlen(betrag), auszahlen(betrag) und auszug() koennen verwendet werdenmeinSparkonto.einzahlen(250.00); // geerbte MethodenmeinSparkonto.auszug();meinSparkonto.auszahlen(10.00);meinSparkonto.auszug();// ausserdem gibt es fuer Instanzen der Klasse Sparkonto die Methode verzinsen()meinSparkonto.verzinsen(); // neu implementierte MethodemeinSparkonto.auszug();

}}

23

Page 28: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Oberon-2

In Oberon-2 erbt die Subklasse nur die Komponenten, die vom Modul der Superklasseexportiert werden. Soll die Klasse Sparkonto die Attribute kontonummer und saldoenthalten, so müssen diese in der Klasse Konto mit einem Stern markiert sein. Damitsind sie auch in anderen Modulen sichtbar und nicht mehr gekapselt. Jeder Program-mier muss für seine Anwendung selbst entscheiden, ob Datenkapselung oder Vererbungwichtiger ist. Beide Konzepte können nur dann parallel verwendet werden, wenn Sub-und Superklasse in einem Modul implementiert sind. Dies geht aber zu Lasten derProgrammlesbarkeit und das Prinzip der Aggregierung wird gelockert.

(* Datei: Konto6/Konto.mod *)(* Beispiel : Vererbung *)MODULE Konto;IMPORT Out;TYPEKonto* = RECORD

kontonummer* : LONGINT; (* Attribute sollen vererbt werden *)saldo * : REAL

END;KontoRef* = POINTER TO Konto;

VAR zaehler* : INTEGER;(* Implementierung des Konstruktors und der Methoden wurde hier ausgelassen *)PROCEDURE (k : KontoRef) Konto*(nummer : LONGINT);PROCEDURE (k : KontoRef) getKontonummer*() : LONGINT;PROCEDURE (k : KontoRef) getSaldo*() : REAL;PROCEDURE (k : KontoRef) einzahlen*(betrag : REAL);PROCEDURE (k : KontoRef) auszahlen*(betrag : REAL);PROCEDURE (k : KontoRef) auszug*();BEGINzaehler := 0;

END Konto.

Dass eine Klasse von einer anderen abgeleitet werden soll, drückt man aus, indemman den Recordtyp der Klasse in Klammern hinter das Schlüsselwort RECORD indie Typdeklaration der neuen Klasse schreibt. Be�ndet sich die Implementierung derSuperklasse in einem anderen Modul, so muss dieses importierte Modul und der Mo-dulname bei der Typableitung mit angegeben werden.Die Klasse Sparkonto übernimmt somit alle Attribute und Methoden der Klasse Konto,inklusive der Konstruktormethode. Im neuen Konstruktor Sparkonto(nummer, zins)wird diese verwendet, um die geerbten Attribute kontonummer und saldo zu initiali-sieren. Das neue Attribut zinssatz muss explizit mit einem Startwert belegt werden.Die zusätzlichen Methoden der Klasse Sparkonto werden wie gewohnt als typgebundeneProzeduren implementiert.

24

Page 29: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

(* Datei: Konto6/Sparkonto.mod *)(* Beispiel : Vererbung *)MODULE Sparkonto;IMPORT Konto, Out;TYPESparkonto* = RECORD (Konto.Konto) (* −−> Vererbung *)

zinssatz * : REAL; (* zusaetzliches Attribut *)END;

SparkontoRef* = POINTER TO Sparkonto;(* Konstuktor der Klasse Sparkonto *)PROCEDURE (sk : SparkontoRef) Sparkonto*(nummer : LONGINT; zins : REAL);BEGINsk.Konto(nummer); (* Konstruktor der Superklasse Konto wird aufgerufen *)sk. zinssatz := zins ;

END Sparkonto;(* neue Methoden fuer Zugri� auf Attribut zinssatz*)PROCEDURE (sk : SparkontoRef) getZinssatz*() : REAL;BEGINRETURN sk.zinssatz;

END getZinssatz;PROCEDURE (sk : SparkontoRef) setZinssatz*(zins : REAL);BEGINsk. zinssatz := zins ;

END setZinssatz;(* neue Methode *)PROCEDURE (sk : SparkontoRef) verzinsen*();BEGINsk.saldo := sk.saldo + (sk. zinssatz*sk.saldo)/100; (* verwendet geerbte Attribute *)

END verzinsen;BEGINEND Sparkonto.

Der NEW -Operator erzeugt ein Objekt vom Typ Sparkonto und speichert einenAdressverweis auf dieses Objekt in meinSparkonto. Die Attribute werden durch denAufruf der Methode Sparkonto(nummer, zins) mit Werten belegt, so dass sich die inAbb. 6 dargestellte Situation ergibt.Für die Instanz meinSparkonto können alle Methoden aufgerufen werden, die in denKlassen Sparkonto und Konto implementiert wurden.

Abbildung 6: Instanz der Klasse Sparkonto

25

Page 30: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

(* Datei: Konto6/KontoTest.mod *)(* Beispiel : Verbung*)MODULE KontoTest;IMPORT Sparkonto, Out;PROCEDURE ProgMain*();VAR meinSparkonto : Sparkonto.SparkontoRef;BEGIN

NEW(meinSparkonto);meinSparkonto.Sparkonto(5613990,3.4);(* jede Instanz der Klasse Sparkonto hat 3 Attribute *)Out.String("Kontonummer: ");Out.Int(meinSparkonto.getKontonummer(),10); (* geerbtes Attribut *)Out.String(" Saldo: ");Out.Real(meinSparkonto.getSaldo(),10); (* geerbtes Attriubut *)Out.String(" Euro Zinssatz: ");Out.Real(meinSparkonto.getZinssatz(),10); (* neu deklariertes Attribut *)Out.Ln;(* Methoden einzahlen(betrag), auszahlen(betrag) und auszug() koennen verwendet werden *)meinSparkonto.einzahlen(250.00); (* geerbte Methoden *)meinSparkonto.auszug();meinSparkonto.auszahlen(10.00);meinSparkonto.auszug();(* ausserdem gibt es fuer Instanzen der Klasse Sparkonto die Methode verzinsen() *)meinSparkonto.verzinsen(); (* neu implementierte Methode *)meinSparkonto.auszug();

END ProgMain;BEGIN

Out.OpenEND KontoTest.

2.7 Reimplementierung

In vielen Fällen reicht es nicht aus, Methoden unverändert von der Superklasse zuerben. Für ein Girokonto muss bspw. beim Auszahlen überprüft werden, ob der Über-ziehungskredit überschritten wird. Ist dies der Fall, darf kein Geld ausgezahlt werden.11

Die Klasse Girokonto kann trotzdem von Konto abgeleitet werden, die geerbte Metho-de muss lediglich an die neue Situation angepasst werden.Wird in einer Subklasse eine Methode der Superklasse mit einer anderen Funktionalitätimplementiert, so bezeichnet man diesen Vorgang als Überschreiben oder Reimplemen-tieren der Methode. Das ist dann der Fall, wenn man die Methode in der Subklassemit gleichem Rückgabewert, Namen und Parametern de�niert und die Anweisungenim Methodenrumpf ändert. Die Objekte der Subklasse haben dann zwei Methoden mitgleichem Namen und gleicher Signatur, jedoch wird die ursprüngliche Methode derSuperklasse von der überschreibenden Methode verdeckt.

11Eine Überprüfung, ob das Konto überzogen wird ist natürlich auch für Konten ohne Kreditrahmensinnvoll. Ich habe jedoch darauf verzichtet.

26

Page 31: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Java

Solange eine Methode in der Superklasse nicht mit �nal gekennzeichnet ist, kann mansie in einer Subklasse überschreiben. Dazu wird der Methodenkopf aus der überge-ordneten Klasse übernommen und die Anweisungen im Methodenrumpf werden derAufgabe entsprechend angepasst.Die Klasse Girokonto wird von Konto abgeleitet und reimplementiert die Methodeauszahlen(betrag). Der gewünschte Betrag wird nicht mehr in allen Fällen vom Kontoabgebucht, sondern nur wenn das Limit nicht überschritten ist. Diese Voraussetzungüberprüft die eingebaute if-Anweisung. Ist die Bedingung erfüllt, ruft der Befehl su-per.auszahlen(betrag) die verdeckte Methode der Superklasse Konto auf. In allen an-deren Fällen wird eine Fehlermeldung ausgegeben.Alle anderen Methoden werden unverändert von Konto übernommen.

//Datei: Konto7/Girokonto.java//Beispiel : Reimplementierungpublic class Girokonto extends Konto{private double limit;public Girokonto(int nummer, double limit){super(nummer);if ( limit < 0)

limit = −limit;this. limit = limit ; // Parameter this zeigt auf das Objekt fuer das die Methode aufgerufen wird

}public double getLimit(){return limit ;

}// Methode fuer schreibenden Zugri� ueberprueft ob limit postiv istpublic void setLimit(double limit){

if ( limit < 0)limit = −limit;

this. limit = limit ;}// −−> Reimplementierungpublic void auszahlen(double betrag){if (betrag <= saldo + limit)super.auszahlen(betrag);

elseSystem.out.println("Limit ueberschritten!");

}}

Genau wie die Klasse Sparkonto erbt Girokonto alle Attribute und Methoden vonKonto. Insbesondere die Methode einzahlen(betrag) kann auf Instanzen der Klasse Gi-rokonto angewendet werden.Ist auf dem Konto noch genügend Geld vorhanden, so verhält sich die Methode aus-zahlen(betrag) - wenn sie für ein Girokonto-Objekt aufgerufen wird - genauso, als wäredas Objekt eine Instanz der Klasse Konto. Der Unterschied zwischen beiden Implemen-tierungen zeigt sich erst wenn man das Konto überzieht. Vom normalen Konto wirdder Betrag abgebucht, während das Girokonto die Auszahlung verweigert.

27

Page 32: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Welche Implementierung verwendet wird, hängt davon ab, von welchem Typ das auf-rufende Objekt ist.

//Datei: Konto7/KontoTest.java//Beispiel : Reimplenetierungpublic class KontoTest{public static void main(String[] args){Konto meinKonto = new Konto(4531088);meinKonto.einzahlen(400.00);meinKonto.auszug();System.out.println("Versuche 100 Euro abzuheben.");meinKonto.auszahlen(100.00); // Methode auszahlen(betrag) der Klasse KontomeinKonto.auszug();System.out.println("Versuche 500 Euro abzuheben.");meinKonto.auszahlen(500.00); // Methode auszahlen(betrag) der Klasse KontomeinKonto.auszug();System.out.println ();Girokonto meinGirokonto = new Girokonto(1733065,100);meinGirokonto.einzahlen(400.00);meinGirokonto.auszug();System.out.println("Versuche 100 Euro abzuheben.");meinGirokonto.auszahlen(100.00); // Methode auszahlen(betrag) der Klasse GirokontomeinGirokonto.auszug();System.out.println("Versuche 500 Euro abzuheben.");meinGirokonto.auszahlen(500.00); // Methode auszahlen(betrag) der Klasse GirokontomeinGirokonto.auszug();

}}

Oberon-2

Oberon-2 ermöglicht ebenfalls das Überschreiben von Methoden. Hierzu deklariert mandie Prozedur mit der gleichen Schnittstelle, bindet sie aber durch den Empfängerpara-meter an die Subklasse. Die verdeckte Methode der Superklasse wird aufgerufen, wennan den Methodennamen ein Pfeil (^) angehängt wird.An der Oberon-Syntax wird nochmal deutlich, dass die Klasse Girokonto tatsächlichüber zwei Varianten der Methode auszahlen(betrag) verfügt, die geerbte Variante abernur dann ausgewählt wird, wenn man dies explizit fordert.Die Methode setLimit(limit) zeigt, warum Attribute nur durch Methoden verändertwerden sollten, auch wenn sie gekapselt sind. Sie stellt sicher, dass der Überziehungs-kredit immer als positiver Wert gespeichert ist. Dies ist ein Detail der Implementierung,das in der Methode auszahlen(betrag) zum Tragen kommt. Wären negative Werte mög-lich, so würde in bestimmen Fällen die Auszahlung verweigert werden, obwohl nochgenügend Geld auf dem Konto ist. Dank der im Konstruktor und in setLimit(limit)realisierten Betragsbildung muss sich der Anwender jedoch nicht um dieses Problemkümmern.

28

Page 33: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

(* Datei: Konto7/Girokonto.mod *)(* Beispiel : Reimplementierung *)MODULE Girokonto;IMPORT Konto, Out;TYPEGirokonto* = RECORD (Konto.Konto)

limit * : REAL;END;

GirokontoRef* = POINTER TO Girokonto;PROCEDURE (gk : GirokontoRef) Girokonto*(nummer : LONGINT; limit : REAL);BEGINgk.Konto(nummer);IF limit < 0 THENlimit := −limit

END;gk. limit := limit ;

END Girokonto;PROCEDURE (gk : GirokontoRef) getLimit*() : REAL;BEGINRETURN gk.limit;

END getLimit;(* Methode fuer schreibenden Zugri� ueberprueft ob limit positiv ist *)PROCEDURE (gk : GirokontoRef) setLimit*(limit : REAL);BEGINIF limit < 0 THENlimit := −limit

END;gk. limit := limit ;

END setLimit;(* −−> Reimplementierung *)PROCEDURE (gk : GirokontoRef) auszahlen*(betrag : REAL);BEGINIF betrag <= gk.saldo + gk.limit THENgk.auszahlen^(betrag);

ELSEOut.String("Limit ueberschritten!"); Out.Ln;

END;END auszahlen;BEGINEND Girokonto.

Von den Klassen Konto und Girokonto wird jeweils eine Instanz erzeugt. Für dasGirokonto wird ein Kreditrahmen von 100e festgelegt. Obwohl beide nach der erstenAuszahlung einen Kontostand von 300e haben, können nur vom normalen Konto 500eabgehoben werden.

(* Datei: Konto7/KontoTest.mod *)(* Beispiel : Reimplementierung*)

MODULE KontoTest;IMPORT Konto, Girokonto, Out;PROCEDURE ProgMain*();VAR meinGirokonto : Girokonto.GirokontoRef;

meinKonto : Konto.KontoRef;

29

Page 34: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

BEGIN

NEW(meinKonto);meinKonto.Konto(4531088);meinKonto.einzahlen(400.00);meinKonto.auszug();Out.String("Versuche 100 Euro abzuheben."); Out.Ln;meinKonto.auszahlen(100.00); (* Methode auszahlen(betrag der Klasse Konto *)meinKonto.auszug();Out.String("Versuche 100 Euro abzuheben."); Out.Ln;meinKonto.auszahlen(500.00); (* Methode auszahlen(betrag der Klasse Konto *)meinKonto.auszug();Out.Ln;NEW(meinGirokonto);meinGirokonto.Girokonto(1733065,100);meinGirokonto.einzahlen(400.00);meinGirokonto.auszug();Out.String("Versuche 100 Euro abzuheben."); Out.Ln;meinGirokonto.auszahlen(100.00); (* Methode auszahlen(betrag) der Klasse Girokonto *)meinGirokonto.auszug();Out.String("Versuche 500 Euro abzuheben."); Out.Ln;meinGirokonto.auszahlen(500.00); (* Methode auszahlen(betrag) der Klasse Girokonto *)meinGirokonto.auszug();

END ProgMain;BEGIN

Out.OpenEND KontoTest.

2.8 Polymorphismus

Durch Vererbung ist es möglich, dass Variablen zur Laufzeit auf Objekte von verschie-denem Typ verweisen, d.h. ein Objekt vom Typ einer Subklasse kann einer Variablender Superklasse zugewiesen werden. Diese Eigenschaft wird Polymorphismus12 genannt.Für jede Variable muss deshalb zwischen ihrem statischen Typ und dem dynamischenTyp unterschieden werden. Der statische Typ ist der Typ, mit dem sie deklariert wur-de. Er bestimmt, auf welche Attribute und Methoden man zugreifen kann, d.h. nurdie Komponenten, die in der Superklasse deklariert wurden, sind ansprechbar. Der dy-namische Typ ist der Typ des Objektes, auf das die Variable zur Laufzeit zeigt. Erbestimmt, welche Methoden aufgerufen werden.Der dynamische Typ ist zur Übersetzungszeit häu�g nicht bekannt. Der Compilerkann bei der Typüberprüfung nur den statischen Typ berücksichtigen. Deshalb mussdie entsprechende Methode dynamisch gebunden werden, d.h. es wird erst zur Laufzeitentschieden, welche Implementierung beim Aufruf einer Methode zum Einsatz kommt.Der Vorteil dieser Zuweisungskompatibilität besteht darin, dass Programme, die bis-her nur Objekte der Superklasse verwenden, in der Lage sind, automatisch auch mit

12Hier bezieht sich der Begri� �Polymorphismus� auf polymorphe Variablen. In der Literatur wirdhäu�g auch von polymorphen Operationen gesprochen, die durch Überschreiben und Überladen vonMethoden erzeugt werden.

30

Page 35: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Objekten der Subklasse zu arbeiten. Programmänderungen sind nicht nötig. Die Pro-gramme können später sogar mit Klassen arbeiten, die bei der Erstellung noch nichtexistierten.Die Variable meinKonto wird als Variable vom Typ Konto deklariert. Im Verlauf desProgrammes verweist sie jedoch auf Objekte verschiedener Typen.Der Befehl meinKonto.auszahlen(500.00) bspw. löst zwei unterschiedliche Reaktionenaus. Beim ersten Aufruf wird das Geld wie gewünscht ausgezahlt, da meinKonto aufein Objekt von Typ Konto zeigt. Zum Zeitpunkt des zweiten Aufrufs verweist die Va-riable jedoch auf eine Instanz der Klasse Girokonto. In diesem Fall wird die Auszahlungverweigert. Dies liegt daran, dass stets die Version der Methode verwendet wird, diezum dynamischen Typ der Variable gehört. Die Methoden beider Klassen heiÿen zwargleich, sind jedoch unterschiedlich implementiert.ObwohlmeinKonto am Ende des Programmes auf ein Sparkonto-Objekt zeigt, kann dieMethode verzinsen() der Klasse Sparkonto nicht auf meinKonto angewendet werden,da verzinsen() in der Klasse Konto nicht existiert. Um auf die Methode verzinsen()zugreifen zu können, ist eine explizite Typumwandlung erforderlich.

Java

//Datei: Konto8/KontoTest.java//Beispiel : Polymorphismuspublic class KontoTest{public static void main(String[] args){Konto meinKonto ; // Variable vom Typ KontomeinKonto = new Konto(4531088); // meinKonto zeigt auf ein Objekt vom Typ KontomeinKonto.einzahlen(300.00);meinKonto.auszug();meinKonto.auszahlen(500.00); // Methode auszahlen(betrag) der Klasse Konto wird aufgerufenmeinKonto.auszug();System.out.println ();meinKonto = new Girokonto(5613990,100); // meinKonto zeigt jetzt auf ein Objekt vom Typ GirokontomeinKonto.einzahlen(300.00);meinKonto.auszug();meinKonto.auszahlen(500.00); // Methode auszahlen(betrag) der Klasse Girokonto wird aufgerufen

// −−> Polymorphismus & dynamische BindungmeinKonto.auszug();System.out.println ();meinKonto = new Sparkonto(1733065,1.25); // meinKonto zeigt jetzt auf ein Objekt vom Typ SparkontomeinKonto.einzahlen(400.00);meinKonto.auszug();meinKonto.auszahlen(100.00); // Methode auszahlen(betrag) der Klasse Sparkonto wird aufgerufenmeinKonto.auszug();

/* meinKonto.verzinsen(); // Fehler : die Klasse Konto kennt die Methode verzinsen() nicht */((Sparkonto)meinKonto).verzinsen();meinKonto.auszug();

}}

31

Page 36: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Oberon-2

(* Datei: Konto8/KontoTest.mod *)(* Beispiel : Polymorphismus*)

MODULE KontoTest;IMPORT Konto, Sparkonto, Girokonto, Out;PROCEDURE ProgMain*();VAR meinKonto : Konto.KontoRef; (* Variable vom Typ Konto. *)

meinSparkonto : Sparkonto.SparkontoRef;meinGirokonto : Girokonto.GirokontoRef;

BEGIN

NEW(meinKonto); (* meinKonto zeigt auf ein Objekt vom Typ Konto *)meinKonto.Konto(4531088);meinKonto.einzahlen(300.00);meinKonto.auszug();meinKonto.auszahlen(500.00); (* Methode auszahlen(betrag) der Klasse Konto wird aufgerufen. *)meinKonto.auszug();Out.Ln;NEW(meinGirokonto);meinGirokonto.Girokonto(5613990,100);(* −−> Polymorphismus *)meinKonto := meinGirokonto; (* meinKonto zeigt jetzt auf ein Objekt vom Typ Girokonto.*)meinKonto.einzahlen(300.00);meinKonto.auszug();meinKonto.auszahlen(500.00); (* Methode auszahlen(betrag) der Klasse Girokonto wird aufgerufen.

−−> dynamische Bindung *)meinKonto.auszug();Out.Ln;NEW(meinSparkonto);meinSparkonto.Sparkonto(1733065,1.25);meinKonto := meinSparkonto; (* meinKonto zeigt jetzt auf ein Objekt vom Typ Sparkonto *)meinKonto.einzahlen(400.00);meinKonto.auszug();meinKonto.auszahlen(100.00); (* Methode auszahlen(betrag) der Klasse Sparkonto wird aufgerufen *)meinKonto.auszug();

(*meinKonto.verzinsen(); // Fehler : die Klasse Konto kennt die Methode verzinsen() nicht *)meinKonto(Sparkonto.SparkontoRef).verzinsen();meinKonto.auszug();

END ProgMain;BEGIN

Out.OpenEND KontoTest.

2.9 Überladen

Überladen bezeichnet die Tatsache, dass mehrere Methoden mit demselben Namen,jedoch unterschiedlicher Signatur deklariert werden dürfen. D.h. die Parameterlistender Methoden müssen sich in mindestens einem Parameter unterscheiden. Entwederist die Anzahl der Parameter verschieden oder sie haben unterschiedliche Typen.Es ist durchaus üblich, dass eine Klasse mehrere Versionen einer Methode anbietet,diese sollten allerdings eine vergleichbare Funktionalität haben.Beim Aufruf einer solche Methode entscheidet der Compiler anhand der übergebenen

32

Page 37: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Parameter, welche Implementierung auszuführen ist.Für ein Konto sollte es bspw. möglich sein bei der Erö�nung zu entscheiden, ob gleichein gewisser Geldbetrag eingezahlt wird oder nicht. Dies bedeutet, dass zwei Konstruk-toren notwendig sind. Gleiches gilt für Sparkonten und Girokonten.

Java

Die Programmiersprache Java erlaubt das Überladen von Methoden und Konstrukto-ren. Der bisherigen Klassenbeschreibungen von Konto wird einfach ein zweiter Kon-struktor hinzugefügt, der mit zwei Parametern deklariert ist. Für die Klassen Sparkontound Girokonto wird ein weiterer Konstruktor mit je drei Argumenten eingeführt.

//Datei: Konto9/Konto.java//Beispiel : Ueberladenclass Konto{static int zaehler = 0;protected int kontonummer;protected double saldo;Konto(int nummer){ // bisheriger Konstruktor mit 1 Parameterzaehler = zaehler + 1;kontonummer = nummer;saldo = 0.00;

}Konto(int nummer, double betrag){ // weiterer Konstruktor mit 2 Parameternzaehler = zaehler + 1;kontonummer = nummer;saldo = betrag;

}// die bereits bekannten Methoden wurde hier weggelassen

}

//Datei: Konto9/Sparkonto.java//Beispiel : Ueberladenclass Sparkonto extends Konto{private double zinssatz;Sparkonto(int nummer, double zins){ // bisheriger Konstruktor mit 2 Parametersuper(nummer); // ruft 1−stelligen Konstruktor der Superklasse aufzinssatz = zins;

}Sparkonto(int nummer, double betrag, double zins){ // weiterer Konstruktor mit 3 Parameternsuper(nummer, betrag); // ruft 2−stelligen Konstruktor der Superklasse aufzinssatz = zins;

}// die bereits bekannten Methoden wurde hier weggelassen

}

33

Page 38: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

//Datei: Konto9/Girokonto.java//Beispiel : Ueberladenclass Girokonto extends Konto{private double limit;Girokonto(int nummer, double limit){ // bisheriger Konstruktor mit 2 Parametersuper(nummer); // ruft 1−stelligen Konstruktor der Superklasse aufif ( limit < 0)

limit = −limit;this. limit = limit ;

}Girokonto(int nummer, double betrag, double limit){ // weiterer Konstruktor mit 2 Parameternsuper(nummer, betrag); // ruft 2−stelligen Konstruktor der Superklasse aufif ( limit < 0)

limit = −limit;this. limit = limit ;

}// die bereits bekannten Methoden wurde hier weggelassen

}

Instanzen der einzelnen Klassen können jetzt wahlweise mit dem bisher bekanntenKonstruktor erzeugt werden, der den Kontostand zu Beginn auf 0.00 setzt, oder manverwendet die neuen Konstruktoren, die bereits Geld auf das Konto einzahlen. Dabeiist besonders bei Objekten der Klassen Sparkonto und Girokonto auf die Reihenfolgeder Argumente zu achten. Zuerst werden Kontonummer und gewünschter Kontostandangegeben, erst danach der Zinssatz bzw. das Limit.

//Datei: Konto9/KontoTest.java//Beispiel : Ueberladenpublic class KontoTest{public static void main(String[] args){Konto meinKonto = new Konto(4531088);meinKonto.einzahlen(300.00);meinKonto.auszug();Konto deinKonto = new Konto(1733065, 200.00);deinKonto.auszug();Sparkonto meinSparkonto = new Sparkonto(5613990, 1.25);meinSparkonto.einzahlen(600.00);meinSparkonto.auszug();Sparkonto deinSparkonto = new Sparkonto(7835406, 500.00, 1.3);deinSparkonto.auszug();Girokonto meinGirokonto = new Girokonto(2571183, 400.00);meinGirokonto.einzahlen(250.00);meinGirokonto.auszug();Girokonto deinGirokonto = new Girokonto(6464951, 600.00, 400.00);deinGirokonto.auszug();

}}

Oberon-2

In Oberon-2 dürfen Namen nicht mehrfach deklariert werden, so dass ein Überladenvon Methoden nicht möglich ist.

34

Page 39: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

3 Beispiel: Mediendatenbank

In diesem Beispiel13 soll eine Anwendung programmiert werden, die verschiedene Ar-ten von Medien verwalten kann. Eine solche Datenbank speichert Informationen überBücher, CDs und Videos und gibt diese auf Anfrage aus.Zunächst ist zu überlegen, welche Daten gespeichert werden. Für Bücher wollen wirAutor, Titel, Verlag und das Erscheinungsjahr festhalten. Eine CD wird mit Titel,Name des Interpreten, Anzahl der Musiktitel und Gesamtspielzeit erfasst. Für Videoswerden Regisseur, Titel und die Länge des Films angegeben. Soll die Anwendung spä-ter als Bestandskatalog einer Buchhandlung oder Bibliothek eingesetzt werden, so istes sinnvoll, neben den bereits genannten Daten, den Preis und einen Kommentar zuspeichern. Auÿerdem sollte jedes Medium durch eine Artikelnummer eindeutig gekenn-zeichnet sein.Es erscheint sinnvoll, die Daten eines Mediums als Einheit zu speichern. Hierzu werdenin der objektorientierten Programmierung Klassen genutzt. Es ist also nahe liegend, fürjede Medienart eine eigene Klasse zu entwickeln, in der alle relevanten Eigenschaftengesammelt sind.Damit die Daten nicht unberechtigt geändert werden, sind sie in der Klasse gekapselt.D.h. die einzelnen Attribute sind nicht nach auÿen hin sichtbar und lassen sich nur überentsprechende Methoden lesen und ändern. Damit andere Programme in der Lage sinddie Datenfelder auszulesen, wird für jedes Attribut eine get-Methode angelegt. Da sichdie meisten Attribute in unserem Beispiel später nicht mehr ändern, gibt es für siekeine Methoden, die es ermöglichen die Attributwerte zu manipulieren. Lediglich derPreis und die Kommentare können durch sogenannte set-Methoden abgeändert wer-den. Dies bedeutet aber auch, dass alle Attributwerte im Konstruktor gesetzt werdenmüssen. Zusätzlich ist eine Methode druckeInfo() de�niert, die die Details des jeweili-gen Mediums ausgibt.Obwohl die Klassen Buch, Cd und Video unterschiedliche Arten von Medien beschrei-ben, sind sie sich sehr ähnlich. Alle drei Klasse besitzen die Attribute code, titel, preisund kommentar. Auÿerdem verfügen alle über die zugehörigen get- und set-Methoden,die sogar identisch zu implementieren sind. Diese o�ensichtliche Code-Duplizierungerhöht den Programmieraufwand unnötig und erschwert die Programmwartung, damögliche Änderungen an mindestens drei Stellen vorgenommen werden müssen. Zu-dem ist es wünschenswert, dass andere Programme nicht zwischen Büchern, CDs undVideos unterscheiden brauchen, sondern diese allgemein als Medium betrachten kön-nen. Insbesondere dann, wenn das Angebot später um weitere Medientypen erweitertwerden soll.

13Hierbei handelte es sich um eine veränderte Variante des Projektes DoME von D.J. Barnes undM. Kölling [BK03, S.263 �].

35

Page 40: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Dieses Problem kann man durch Vererbung lösen. Anstatt die Klassen völlig unab-hängig voneinander zu de�nieren, wird zuerst eine Klasse Medium beschrieben, die dieGemeinsamkeiten der drei Klassen zusammenfasst. Die Klassen Buch, Cd und Videowerden von dieser Klasse abgeleitet und implementieren nur die typspezi�schen Eigen-schaften von Büchern, CDs bzw. Videos. Somit ergibt sich die in Abb. 7 dargestellteKlassenhierarchie. Der grundlegende Vorteil dieser Vorgehensweise ist, dass man ge-meinsame Eigenschaften nur einmal beschreibt.Sobald die Klassen Medium, Buch, Cd und Video de�niert sind, können Instanzen derKlassen erzeugt werden. Abgesehen von diesen Klassen wird aber noch eine weitereKlasse benötigt, die die Objekte verwaltet. Die Klasse Datenbank verfügt über ein At-tribut medien, das die einzelnen Medien-Objekte sammelt. Auÿerdem implementiertsie eine Methode zum Erfassen neuer Objekte, die sowohl mit Objekten vom TypMedi-um, als auch mit Instanzen aller Unterklassen vonMedium arbeiten kann. Die Methodeau�isten() gibt eine Liste aller Medien auf der Konsole aus.

Abbildung 7: Klassendiagramm Mediendatenbank

Java

In der Klasse Medium werden alle Attribute deklariert, die verschiedene Medien ge-mein haben. Sie sind mit dem Schlüsselwort protected gekennzeichnet, um sie andie Subklassen zu vererben. Zusätzlich zu den bereits genannten Attributen wird eineKlassenvariable zaehler de�niert, die zählt, wie viele Objekte erzeugt wurden.

36

Page 41: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Der zweistellige Konstruktor Medium(titel, preis) initialisiert die einzelnen Attribute.Er verwendet die Klassenvariable zaehler, um automatisch eine Artikelnummer zu er-zeugen. Die Werte von titel und preis werden, durch die Argumente des Konstruktorsfestgelegt und der Kommentar wird zunächst mit einer leeren Zeichenkette initialisiert.Auÿerdem muss im Konstruktor der Wert von zaehler erhöht werden. Auf diese Weisewird ein Instanzenzähler implementiert, da Medium(titel, preis) immer dann aufgeru-fen wird, wenn man ein neues Objekt erzeugt.Die get- und set-Methoden der Attribute sind mit dem Modi�zierer public gekenn-zeichnet, so dass andere Programme die Möglichkeit haben sie zu verwenden.Die Methode druckeInfo() gibt alle Datenfelder, die verschiedenartige Medien gemein-sam haben, auf die Konsole aus.

// Datei: Medien/Medium.javapublic class Medium {protected static int zaehler = 0;protected int code ;protected String titel;protected double preis;protected String kommentar;public Medium(String titel, double preis){this.zaehler += 1;this.code = 100000 + this.zaehler;this. titel = titel ;this. preis = preis ;this.kommentar = "";

}public int getCode(){return this.code;

}public String getTitel(){return this.titel ;

}public double getPreis(){return this.preis;

}public void setPreis(double preis){this. preis = preis ;

}public String getKommentar(){return this.kommentar;

}public void setKommentar(String kommentar){this.kommentar = kommentar;

}public void druckeInfo(){System.out.println("Code: "+this.code);System.out.println("Titel: "+this. titel );System.out.println("Preis: "+this.preis+" Euro");System.out.println("Kommentar: "+this.kommentar);System.out.println ();

}}

37

Page 42: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Da die Klasse Buch von Medium abgeleitet wird, ist es nicht nötig, die Attribute co-de, titel, preis und kommentar erneut zu deklarieren. Genau wie die zugehörigen get-und set-Methoden erbt Buch diese Attribute von der Superklasse. Es müssen somitnur die Attribute autor, verlag und erscheinungsjahr, einschlieÿlich der jeweiligen get-Methoden, de�niert werden.Weiterhin implementiert Buch einen eigenen Konstruktor Buch(titel, autor, verlag,jahr, preis). Dieser ruft zunächst den Konstruktor der Superklasse Medium auf undübergibt ihm die Argumente titel und autor. Durch diesen Aufruf werden die geerbtenAttribute mit Werten belegt und die Klassenvariable zaehler wird erhöht.Von der Superklasse Medium erbt Buch auÿerdem die Methode druckeInfo(). Diesekann jedoch nicht alle Daten eines Buches ausgeben, da bspw. der Autor in der Su-perklasse nicht bekannt ist. Die Methode druckeInfo() muss also in Buch mit eineranderen Funktionalität implementiert werden. Die neue Implementierung überschreibtdann die Variante der Klasse Medium.

// Datei: Medien/Buch.javapublic class Buch extends Medium{protected String autor;protected String verlag;protected int erscheinungsjahr;public Buch(String titel , String autor, String verlag , int jahr , double preis){super(titel , preis );this.autor = autor;this.verlag = verlag;this.erscheinungsjahr = jahr;

}public String getAutor(){return this.autor;

}public String getVerlag(){return this.verlag;

}public int getErscheinungsjahr(){return this.erscheinungsjahr;

}public void druckeInfo(){System.out.println("Code: "+this.code);System.out.println("Titel: "+this. titel );System.out.println("Autor: "+this.autor);System.out.println("Verlag: "+this.verlag+", "+this.erscheinungsjahr);System.out.println("Preis: "+this.preis+" Euro");System.out.println("Kommentar: "+this.kommentar);System.out.println ();

}}

38

Page 43: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Für die Klassen Cd und Video gilt das Gleiche wie für Buch. Sie werden von Mediumabgeleitet und de�nieren lediglich weitere Attribute und Methoden, um die spezi�schenEigenschaften von CDs bzw. Videos zu implementieren.Die Konstruktoren Cd(titel, interpret, titelanz, zeit, preis) und Video(titel, reg, zeit,preis) enthalten als ersten Befehl den Aufruf des Konstruktors der Klasse Medium.Dies bedeutet insbesondere, dass die Klassenvariable zaehler alle Medienobjekte zählt- unabhängig davon, ob es sich um Bücher, CDs oder Videos handelt.Genau wie in der Klasse Buch muss die Methode druckeInfo() in Cd und Video erneutimplementiert werden. Da sich die einzelnen Implementierungen voneinander unter-scheiden, kann diese Aufgabe nicht komplett in die Superklasse verschoben werden.

// Datei: Medien/Cd.javapublic class Cd extends Medium{protected String interpret;protected int titelanzahl;protected int spieldauer;public Cd(String titel , String interpret , int titelanz , int zeit , double preis){super(titel , preis );this. interpret = interpret ;this. titelanzahl = titelanz ;this. spieldauer = zeit ;

}public String getInterpret(){return this.interpret;

}public int getTitelanzahl(){return this.titelanzahl ;

}public int getSpieldauer(){return this.spieldauer;

}public void druckeInfo(){System.out.println("Code: "+this.code);System.out.println("Titel: "+this. titel );System.out.println("Interpret: "+this.interpret );System.out.println("Spieldauer: "+this.spieldauer+" min, "+this.titelanzahl+" Titel");System.out.println("Preis: "+this.preis+" Euro");System.out.println("Kommentar: "+this.kommentar);System.out.println ();

}}

// Datei: Medien/Video.javapublic class Video extends Medium{protected String regisseur;protected int spieldauer;public Video(String titel , String reg , int zeit , double preis){super(titel , preis );this. regisseur = reg;this. spieldauer = zeit ;

}

39

Page 44: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

public String getRegisseur(){return this.regisseur;

}public int getSpieldauer(){return this.spieldauer;

}public void druckeInfo(){System.out.println("Code: "+this.code);System.out.println("Titel: "+this. titel );System.out.println("Regisseur: "+this.regisseur);System.out.println("Spieldauer: "+this.spieldauer+" min");System.out.println("Preis: "+this.preis+" Euro");System.out.println("Kommentar: "+this.kommentar);System.out.println ();

}}

Die Klasse Datenbank verwendet die Klasse Vector aus dem Paket java.util. DiesesPaket muss zunächst durch eine import-Anweisung importiert werden. Vector im-plementiert ein dynamisches Array, auf dessen Komponenten über einen ganzzahligenIndex zugegri�en werden kann. Bei der Deklaration der Variable medien wird in spit-zen Klammern angegeben, von welchem Typ die Komponenten des Vektors sind.14

Der Konstruktor Datenbank() erzeugt ein Vector -Objekt, indem der Konstruktor Vec-tor() der Klasse Vector aufgerufen wird. Dabei muss erneut angegeben werden, dassdie Komponenten vom Typ Medium sein sollen. Der erzeugte Vektor ist zunächst leer.Die Methode erfasseMedium(med) fügt neue Objekte in den Vektor medien ein. Dazuwird die Methode add(object) aus der Klasse Vector auf medien angewendet. add(med)hängt das Objekt med ans Ende des Vektors an. Auf diese Art und Weise werdenInstanzen der Klasse Medium gesammelt.Die Methode au�isten() durchläuft die Sammlung und ruft für jede Komponente dieMethode druckeInfo() auf. Zuvor muss das Element jedoch mittels get(i) geholt wer-den. Die Methoden get(i) und size() sind in der Klasse Vector implementiert.

// Datei: Medien/Datenbank.javaimport java.util .*;public class Datenbank{private Vector<Medium> medien;public Datenbank(){this.medien = new Vector<Medium>();

}

14Die Klasse Vector steht in JDK 1.5 als generische Klasse zur Verfügung, d.h. sie kann mit ver-schiedenen Arten von Objekten arbeiten. Dies vereinfacht die Programmierung, da man den statischenTyp der Rückgabewerte der Vector -Methoden festlegen kann. Bisher wurden Objekte als Instanzender Klasse Object übergeben und mussten explizit umgewandelt werden. Siehe auch [Mös98, S.91],[Cla98, S.26] oder vergleiche [API1.4] und [API1.5].

40

Page 45: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

public void erfasseMedium(Medium med){this.medien.add(med);

}public void au�isten(){Medium med;for (int i=0; i < medien.size (); i++){med =this.medien.get(i);med.druckeInfo();

}}

}

In der Klasse Datenbank werden die Eigenschaften und das Verhalten einer Datenbankbeschrieben. Die Datenbank selber existiert noch nicht. Deshalb wird im Testprogrammzunächst eine Instanz der Klasse Datenbank erzeugt. Es ist möglich verschiedene Daten-banken anzulegen, dazu müssen lediglich weitere Instanzen der Klasse gebildet werden.In die Datenbank werden durch die Methode erfasseMedium(med) nacheinander ver-schiedene Medien eingefügt. Dabei fällt auf, dass die Methode auch Objekte vom TypBuch, Cd oder Video verarbeiten kann. Dies ist möglich, da es sich um Subklassen derKlasse Medium handelt. In der De�niton von erfasseMedium(med) ist med als Varia-ble vom Typ Medium deklariert. Durch diese Festlegung wird lediglich der statischeTyp bestimmt. Zur Ausführungszeit kann med auch auf Objekte eines anderen, vonMedium abgeleiteten Typs verweisen. Die Polymorphie von Variablen reduziert denProgrammieraufwand erheblich, da man sonst mehrere Versionen15 der Methode er-fasseMedium(med) implementieren müsste. Zudem könnten Bücher, CDs und Videosnicht innerhalb eines Vektors verwaltet werden.Schlieÿlich wird der Inhalt der Datenbank ausgegeben. Die Methode au�isten() ruftfür jedes Medium in der Datenbank die Methode druckInfo() auf. Welche Implemen-tierung dieser Methode ausgeführt wird, legt der Übersetzer - in Abhängigkeit vomdynamischen Typ der Variable - erst zur Laufzeit fest.

// Datei: Medien/TestMedienDB.javapublic class TestMedienDB{public static void main(String[] args){Datenbank db = new Datenbank();db.erfasseMedium(new Medium("Herr der Ringe", 11.00));db.erfasseMedium(new Buch("Sprechen Sie Java","Hanspeter Moessenboeck", "dpunkt.verlag", 2001, 28.00));db.erfasseMedium(new Cd("No Angel","Dido",13,90,15.00));db.erfasseMedium(new Video("X−Men","Bryan Singer",100,21.00));db. au�isten ();

}}

15erfasseBuch(buch), erfasseCd(cd) und erfasseVideo(video).

41

Page 46: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Oberon-2

Die Anwendung Mediendatenbank lässt sich mit einigen Anpassungen auch in Oberon-2 umsetzen.Für jede Klasse wird ein eigenes Modul geschrieben, in dem die Datenfelder in einemRECORD deklariert werden. Die instanzspezi�schen Methoden werden als typgebun-dene Prozeduren implementiert.Da Oberon-2 nicht über einen eigenen Datentyp für Zeichenketten verfügt, werdendie Attribute titel, kommentar, autor usw. als ARRAY 100 OF CHAR deklariert.Dies bedeutet jedoch, dass die Einträge maximal 100 Zeichen lang sein dürfen. Für dieWertzuweisung wird die vorde�nierte Prozedur COPY(s, t) genutzt. Diese Prozedurkopiert den Wert des Zeichenfeldes s in das Feld t.Im Modul Medium wird als erste Prozedur eine Klassenmethode NEWMedium(titel,preis) implementiert. Diese Methode ersetzt den in anderen objektorientierten Pro-grammiersprachen üblichen Konstruktor. Anders als im Beispiel Konten ist derNEW -Operator diesmal in der Konstruktormethode enthalten, d.h. die Methode erzeugt undinitialisiert die Objekte. Anschlieÿend werden die Objekte als Rückgabewert an dieaufrufende Stelle zurückgeben. Das bedeutet, dass eine Variable des passenden Refe-renztyps das Objekt entgegennehmen muss. Die Klassen Buch, Cd und Video besitzenmit NEWBuch(titel, autor, verlag, jahr, preis), NEWCd(titel, interpret, titelanz, zeit,preis) bzw. NEWVideo(Titel, reg, zeit, preis) ebenfalls eine Klassenmethode, die denKonstruktor ersetzt.Aus Sicherheitsgründen sollten Attribute immer über Methoden angesprochen wer-den. Deshalb wurden get- und set-Methoden implementiert, obwohl die Datenfelderö�entlich sind. Anders als in Java sind die Methoden getTitel(titel), getKommen-tar(kommentar) u.a. nicht als Funktionen implementiert. Da Arrays nicht Rückga-bewert einer Funktion sein können, wird das Ergebnis an einen Referenzparameterübergeben.

(* Datei: Medien/Medium.mod *)MODULE Medium;IMPORT Out;TYPEMedium* = RECORD

code* : LONGINT;titel * : ARRAY 100 OF CHAR;preis * : REAL;kommentar* : ARRAY 100 OF CHAR;

END;MediumRef* = POINTER TO Medium;

VAR zaehler* : INTEGER;

42

Page 47: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

PROCEDURE NEWMedium*(titel : ARRAY 100 OF CHAR; preis : REAL) : MediumRef;VAR tmp : MediumRef;BEGINNEW(tmp);INC(zaehler);tmp.code := 100000 + zaehler;COPY(titel, tmp.titel);tmp.preis := preis ;tmp.kommentar := "";RETURN tmp;

END NEWMedium;PROCEDURE (m : MediumRef) getCode*() : LONGINT;BEGINRETURN m.code;

END getCode;PROCEDURE (m : MediumRef) getTitel*(VAR titel : ARRAY 100 OF CHAR) ;BEGINCOPY(m.titel, titel);

END getTitel;PROCEDURE (m : MediumRef) getPreis*() : REAL;BEGINRETURN m.preis;

END getPreis;PROCEDURE (m : MediumRef) setPreis*(preis : REAL);BEGINm.preis := preis ;

END setPreis;PROCEDURE (m : MediumRef) getKommentar*(VAR kommentar : ARRAY 100 OF CHAR);BEGINCOPY(m.kommentar, kommentar);

END getKommentar;PROCEDURE (m : MediumRef) setKommentar*(kommentar : ARRAY 100 OF CHAR);BEGINCOPY(kommentar, m.kommentar);

END setKommentar;PROCEDURE (m : MediumRef) druckeInfo*();BEGINOut.String("Code: "); Out.Int(m.code, 7); Out.Ln;Out.String("Titel: " ); Out.String(m.titel ); Out.Ln;Out.String("Preis: " ); Out.Real(m.preis , 5); Out.String(" Euro"); Out.Ln;Out.String("Kommentar: "); Out.String(m.kommentar); Out.Ln;Out.Ln;

END druckeInfo;BEGINzaehler := 0;

END Medium.

(* Datei: Medien/Buch.mod *)MODULE Buch;IMPORT Out, Medium;TYPEBuch* = RECORD (Medium.Medium)

autor : ARRAY 100 OF CHAR;verlag : ARRAY 100 OF CHAR;erscheinungsjahr : INTEGER;

END;BuchRef* = POINTER TO Buch;

43

Page 48: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

PROCEDURE NEWBuch*(titel, autor, verlag : ARRAY 100 OF CHAR; jahr : INTEGER; preis : REAL) : BuchRef;VAR tmp : BuchRef;BEGINNEW(tmp);INC(Medium.zaehler);tmp.code := 100000 + Medium.zaehler;COPY(titel, tmp.titel);COPY(autor, tmp.autor);COPY(verlag, tmp.verlag);tmp.erscheinungsjahr := jahr;tmp.preis := preis ;tmp.kommentar := "";RETURN tmp;

END NEWBuch;PROCEDURE (b : BuchRef) getAutor*(VAR autor : ARRAY 100 OF CHAR);BEGINCOPY(b.autor, autor);

END getAutor;PROCEDURE (b : BuchRef) getVerlag*(VAR verlag : ARRAY 100 OF CHAR);BEGINCOPY(b.verlag, verlag);END getVerlag;PROCEDURE (b : BuchRef) getErscheinungsjahr*() : INTEGER;BEGINRETURN b.erscheinungsjahr;

END getErscheinungsjahr;PROCEDURE (b : BuchRef) druckeInfo*();BEGINOut.String("Code: "); Out.Int(b.code , 7); Out.Ln;Out.String("Titel: " ); Out.String(b. titel ); Out.Ln;Out.String("Autor: "); Out.String(b.autor); Out.Ln;Out.String("Verlag: "); Out.String(b.verlag ); Out.String(", " ); Out.Int(b.erscheinungsjahr ,4); Out.Ln;Out.String("Preis: " ); Out.Real(b.preis , 5); Out.String(" Euro"); Out.Ln;Out.String("Kommentar: "); Out.String(b.kommentar); Out.Ln;Out.Ln;

END druckeInfo;BEGINEND Buch.

(* Datei: Medien/Cd.mod *)MODULE Cd;IMPORT Out, Medium;TYPECd* = RECORD (Medium.Medium)

interpret : ARRAY 100 OF CHAR;titelanzahl , spieldauer : INTEGER;

END;CdRef* = POINTER TO Cd;

PROCEDURE NEWCd*(titel, interpret : ARRAY 100 OF CHAR; titelanz, zeit : INTEGER; preis : REAL) : CdRef;VAR tmp : CdRef;BEGINNEW(tmp);INC(Medium.zaehler);tmp.code := 100000 + Medium.zaehler;COPY(titel, tmp.titel);COPY(interpret, tmp.interpret);tmp.titelanzahl := titelanz ;tmp.spieldauer := zeit ;tmp.preis := preis ;tmp.kommentar := "";RETURN tmp;

END NEWCd;

44

Page 49: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

PROCEDURE (c : CdRef) getInterpret*(VAR interpret : ARRAY 100 OF CHAR);BEGINCOPY(c.interpret, interpret);

END getInterpret;PROCEDURE (c : CdRef) getTitelanzahl*() : INTEGER;BEGINRETURN c.titelanzahl;

END getTitelanzahl;PROCEDURE (c : CdRef) getSpieldauer*() : INTEGER;BEGINRETURN c.spieldauer;

END getSpieldauer;PROCEDURE (c : CdRef) druckeInfo*();BEGINOut.String("Code: "); Out.Int(c.code , 7); Out.Ln;Out.String("Titel: " ); Out.String(c. titel ); Out.Ln;Out.String("Interpret: " ); Out.String(c. interpret ); Out.Ln;Out.String("Spieldauer: "); Out.Int(c.spieldauer , 3); Out.String(" min, ");Out.Int(c. titelanzahl ,3); Out.String(" Titel"); Out.Ln;Out.String("Preis: " ); Out.Real(c.preis , 5); Out.String(" Euro"); Out.Ln;Out.String("Kommentar: "); Out.String(c.kommentar); Out.Ln;Out.Ln;

END druckeInfo;BEGINEND Cd.

(* Datei: Medien/Video.mod *)MODULE Video;IMPORT Out, Medium;TYPEVideo* = RECORD (Medium.Medium)

regisseur : ARRAY 100 OF CHAR;spieldauer : INTEGER;

END;VideoRef* = POINTER TO Video;

PROCEDURE NEWVideo*(titel, regisseur : ARRAY 100 OF CHAR; zeit : INTEGER; preis : REAL) : VideoRef;VAR tmp : VideoRef;BEGINNEW(tmp);INC(Medium.zaehler);tmp.code := 100000 + Medium.zaehler;COPY(titel, tmp.titel);COPY(regisseur, tmp.regisseur);tmp.spieldauer := zeit ;tmp.preis := preis ;tmp.kommentar := "";RETURN tmp;

END NEWVideo;PROCEDURE (v : VideoRef) getRegisseur*(VAR reg : ARRAY 100 OF CHAR);BEGINCOPY(v.regisseur, reg);

END getRegisseur;PROCEDURE (v : VideoRef) getSpieldauer*() : INTEGER;BEGINRETURN v.spieldauer;

END getSpieldauer;

45

Page 50: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

PROCEDURE (v : VideoRef) druckeInfo*();BEGINOut.String("Code: "); Out.Int(v.code , 7); Out.Ln;Out.String("Titel: " ); Out.String(v. titel ); Out.Ln;Out.String("Regisseur: "); Out.String(v. regisseur ); Out.Ln;Out.String("Spieldauer: "); Out.Int(v.spieldauer ,3); Out.String(" min"); Out.Ln;Out.String("Preis: " ); Out.Real(v.preis , 5); Out.String(" Euro"); Out.Ln;Out.String("Kommentar: "); Out.String(v.kommentar); Out.Ln;Out.Ln;

END druckeInfo;BEGINEND Video.

Oberon-2 verfügt zwar über sogenannte o�ene Arrays, diese dürfen aber nicht innerhalbeinerRECORD-Deklaration verwendet werden. Deshalb musste im Modul Datenbankauf ein statisches Array des Gröÿe 100 zurückgegri�en werden, dass auf Objekte vomTyp Medium verweist. Somit kann jede Datenbank maximal 100 Einträge speichern.Damit die Methode au�isten() nur den Teil des Arrays durchläuft, der tatsächlichverwendet wird, speichert das Attribut length die Länge des belegten Abschnitts. Nurdas Modul Datenbank benutzt dieses Attribut, weshalb es nicht exportiert wird.Die Methode NEWDatenbank() erzeugt zunächst eine Instanz der Klasse Datenbankund speichert einen Adressverweis auf dieses Objekt in einer temporären Variable. DieFelder des Arrays werden auf den Wert NIL gesetzt, d.h. sie verweisen auf kein Objekt.Der Wert des Attributs length wird mit 0 initialisiert. Anschlieÿend wird das erzeugteObjekt an die Stelle des Funktionsaufrufes zurückgegeben.Durch die Methode erfasseMedium(med) wird das Objekt, dass med referenziert demnächsten freien Feld von medien zugewiesen und length um 1 erhöht. Ist kein freiesFeld verfügbar, gibt die Methode eine Fehlermeldung aus.

(* Datei: Medien/Datenbank.mod *)MODULE Datenbank;IMPORT Out, Medium;TYPEDatenbank* = RECORD

medien* : ARRAY 100 OF Medium.MediumRef;length : INTEGER;

END;DatenbankRef* = POINTER TO Datenbank;

PROCEDURE NEWDatenbank*() : DatenbankRef;VAR tmp : DatenbankRef;

i : INTEGER;BEGINNEW(tmp);FOR i:= 0 TO 99 DOtmp.medien[i] := NIL;

END;tmp.length := 0;RETURN tmp;

END NEWDatenbank;

46

Page 51: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

PROCEDURE (db : DatenbankRef) erfasseMedium*(med : Medium.MediumRef);BEGINIF db.length < 100 THENdb.medien[db.length] := med;INC(db.length);

ELSEOut.String("Datenbank ist voll, Medium öknnte nicht eingefuegt werden.");

END;END erfasseMedium;PROCEDURE (db : DatenbankRef) au�isten*();VAR i : INTEGER;BEGINFOR i:= 0 TO db.length−1 DOdb.medien[i ].druckeInfo();

END;END au�isten;BEGINEND Datenbank.

Das Testprogramm importiert alle Module, die es verwendet, da sonst die darin de-�nierten Namen nicht bekannt sind. Um die Komponenten eines Moduls zu nutzen,muss der Name dieses Moduls immer mit angegeben sein. Dies bedeutet insbesonde-re, dass die Klassenmethoden NEWDatenbank(), NEWMedium(titel, preis) usw. nurüber den Modulnamen angesprochen werden können. Typgebundene Prozeduren, wiez.B. erfasseMedium(med), sind an ein Objekt der Klasse gebunden. Deshalb kann derAufruf über den zugehörigen Variablennamen erfolgen.

(* Datei: Medien/TestMedienDB.mod *)MODULE TestMedienDB;IMPORT Out, Datenbank, Medium, Buch, Cd, Video;PROCEDURE ProgMain*();VAR db : Datenbank.DatenbankRef;BEGINdb := Datenbank.NEWDatenbank();db.erfasseMedium(Medium.NEWMedium("Herr der Ringe", 11.00));db.erfasseMedium(Buch.NEWBuch("OPP mit Oberon−2","Hanspeter Moessenboeck","dpunkt.verlag", 2001, 28.00));db.erfasseMedium(Cd.NEWCd("No Angel", "Dido", 13, 90, 15.00));db.erfasseMedium(Video.NEWVideo("X−Men", "Bryan Singer", 100, 21.00));db. au�isten ();

END ProgMain;BEGINOut.Open;

END TestMedienDB.

47

Page 52: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

4 Beispiel: Geometrische Figuren

Das letzte Beispiel stellt verschiedene Methoden zur Manipulation von geometrischenFiguren zur Verfügung. Für jede Art von Figur kann man die Fläche berechnen, dieFigur verschieben oder strecken und sie zeichnen. Die Aufgaben sind für alle Figurengleich, jedoch ist die korrekte Implementierung einiger Methoden von der jeweiligenFigur abhängig. Jede Figur benötigt somit eine eigene Klasse, in der charakteristischeEigenschaften und das zugehörige Verhalten beschrieben sind. Damit Programme, dieObjekte dieser Klassen benutzen, nicht zwischen den unterschiedlichen Varianten un-terscheiden müssen, wird eine allgemeine Klasse Figur eingeführt. Die konkreten Fi-guren Rechteck, Quadrat und Kreis werden aus dieser Klasse abgeleitet.Bleibt die Frage, welche Komponenten in der Superklasse zu de�nieren sind. Ein ebe-nes Rechteck wird durch einen Punkt sowie Höhe und Breite eindeutig bestimmt. FürQuadrat und Kreis genügen ein Punkt und die Höhe bzw. der Radius als Angaben.Da jeder Figurtyp einen Referenzpunkt zur Bestimmung der Lage benötigt, scheint essinnvoll die x- und y-Koordinate dieses Punktes als Attribute in Figur einzuführen. Dienotwendigen Maÿangaben sind bei den einzelnen Figuren unterschiedlich und gehörendeshalb in die zugehörigen Subklassen.Damit die Methoden getFlaeche(), verschieben(dx, dy) , strecken(faktor) und zeich-nen() für eine Variable vom Typ Figur aufgerufen werden können, müssen sie in derKlasse Figur deklariert sein. Dies liegt daran, dass zur Übersetzungszeit der statischeTyp der Variable16 festlegt, welche Methoden ausführbar sind. Die Methode verschie-ben(dx, dy) kann leicht implementiert werden. Alle anderen bereiten jedoch Probleme,da sie auf Längenangaben angewiesen sind, die in Figur nicht zur Verfügung stehen.Zur Lösung dieses Problems gibt es in objektorientierten Sprachen die Möglichkeit,abstrakte Methoden ohne Anweisungsblock zu de�nieren. Eine Klasse, die abstrakteMethoden enthält, ist damit automatisch eine abstrakte Klasse. Von solchen Klassensollten keine Instanzen erzeugt werden. Sie dienen ausschlieÿlich als Superklasse fürandere Klassen.Die Klasse Figur wird somit als abstrakte Klasse implementiert. Die abstrakten Me-thoden getFlaeche(), strecken(faktor) und zeichnen() werden in den Klassen Rechteck,Quadrat und Kreis überschrieben und erhalten so ihre Funktionalität. Insgesamt ergibtsich die in Abb. 8 dargestellte Klassenhierarchie.

16Siehe auch Abschnitt 2.8 über Polymorphismus.

48

Page 53: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Abbildung 8: Klassendiagramm geometische Figuren

Java

Abstrakte Klassen und Methoden sind in Java mit dem Schlüsselwort abstract gekenn-zeichnet. Sobald eine Klasse eine abstrakte Methode enthält, muss auch die Klasse alsabstrakt de�niert werden. Der Java-Compiler verhindert dann, dass von dieser Klasseeine Instanz erzeugt wird. Der Versuch, den new -Operator auf eine abstrakte Klasseanzuwenden, führt zu einem Fehler.Neben den bereits genannten Methoden zur Manipulation wurden weitere Methodenergänzt, die Informationen über das Objekt liefern. Anhand dieser Methoden wird dasPrinzip des Information Hiding noch einmal deutlich. Die Attribute können nicht di-rekt angesprochen werden. Um die Informationen trotzdem verfügbar zu machen, sindspezielle get-Methoden implementiert. Diese Methoden geben die Attributwerte jedochnicht als Integer oder Double zurück sondern als String. Änderung des Datentyps derAttribute wirken sich deshalb nicht auf den Anwender aus.

//Datei: Figuren/Figur.javaimport java.awt.*;public abstract class Figur{protected int xpos, ypos;protected Figur(int x, int y){this.xpos = x;this.ypos = y;

}

49

Page 54: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

public abstract String getTyp();public String getPosition(){return "("+this.xpos+";"+this.ypos+") ";

}public abstract String getLaengen();public abstract double getFlaeche();public void verscheiben(int dx, int dy){this.xpos += dx;this.ypos += dy;

}public abstract void strecken(double faktor);public abstract void zeichnen(Graphics g);

}

Die Klassen Rechteck, Quadrat und Kreis deklarieren die spezi�schen Attribute derFigurtypen und implementieren die abstrakten Methoden der Klasse Figur.Die Methoden getPosition() und verschieben(dx, dy) können unverändert von der Su-perklasse geerbt werden.Zum Zeichnen der Figuren wurden Methoden der Klasse Graphics aus den Paket ja-va.awt genutzt.17

//Datei: Figuren/Rechteck.javaimport java.awt.*;public class Rechteck extends Figur{protected double breite, hoehe;public Rechteck(int x, int y, double breite, double hoehe){super(x,y);this. breite = breite ;this.hoehe = hoehe;

}public String getTyp(){return "Rechteck";

}public String getLaengen(){return "Breite = "+this.breite+" Hoehe = "+this.hoehe;

}public double getFlaeche(){

return this.breite*this.hoehe;}public void strecken(double faktor){this. breite *= faktor;this.hoehe *= faktor;

}public void zeichnen(Graphics g){g.drawRect(this.xpos, this.ypos, (int)this. breite , ( int)this.hoehe);

}}

17Siehe [Abt02, S. 205 �] oder [API1.5].

50

Page 55: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

//Datei: Figuren/Quadrat.javaimport java.awt.*;public class Quadrat extends Figur{protected double hoehe;public Quadrat(int x, int y, double hoehe){super(x,y);this.hoehe = hoehe;

}public String getTyp(){return "Quadrat";

}public String getLaengen(){return "Hoehe = "+this.hoehe;

}public double getFlaeche(){return this.hoehe*this.hoehe;

}public void strecken(double faktor){this.hoehe *= faktor;

}public void zeichnen(Graphics g){g.drawRect(this.xpos, this.ypos, (int)this.hoehe, (int)this.hoehe);

}}

//Datei: Figuren/Kreis.javaimport java.awt.*;public class Kreis extends Figur{protected double radius;public Kreis(int x, int y, double radius){super(x,y);this.radius = radius;

}public String getTyp(){return "Kreis";

}public String getLaengen(){return "Radius = "+this.radius;

}public double getFlaeche(){

return 3.14*this.radius*this.radius;}public void strecken(double faktor){this.radius *= faktor;

}public void zeichnen(Graphics g){

g.drawOval(this.xpos−(int)this.radius, this.ypos−(int)this.radius, (int)(2*this.radius ), ( int)(2*this.radius ));}

}

51

Page 56: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Im ersten Testprogramm werden Instanzen der Klassen Quadrat und Kreis erzeugtund in Variablen des jeweiligen Typs gespeichert. Auf diese Objekte können die dekla-rierten Methoden wie gewohnt angewendet werden.Die Methode zeichnen(g) benötigt ein Fenster in dem die Befehle der Klasse Graphicszeichnen. Das Paket java.awt stellt diese und andere gra�sche Komponenten18 zur Ver-fügung. Das Programm TestFigur1 verwendet die Klasse Frame.Zunächst wird die Methode paint überschrieben. Sie spezi�ziert, was im Fenster dar-zustellen ist. Der Konstruktor der Klasse TestFigur1 legt die Gestalt des Fensters festund aktiviert den Button zum Schlieÿen. Im Hauptprogramm muss das Fenster dannnoch erzeugt werden.

//Datei: Figuren/TestFigur1.javaimport java.awt.*;import java.awt.event.*;public class TestFigur1 extends Frame{

// die Methode paint wird automatisch ausgefuehrt, wenn eine gra�sche Komponente gezeichnet wirdpublic void paint (Graphics g){

Quadrat testQ = new Quadrat(100,100,10);Kreis testK = new Kreis(500,200,80);for (int i = 0; i < 18; i++) {

testQ.zeichnen(g);testQ.strecken (1.2);testK.zeichnen(g);testK.verscheiben(10,0);

}}// folgende Programmteile werden zum Zeichnen benoetigt// Konstruktor initialisiert das Fenster , in dem gezeichnet wirdpublic TestFigur1(){super("Figuren"); // Titel des FensterssetVisible (true); // Fenster anzeigensetSize (1000,600); // Groesse des FenstersaddWindowListener(new WindowAdapter() {public void windowClosing ( WindowEvent e) {System.exit(0);

}});

}public static void main(String args[]){TestFigur1 frame = new TestFigur1(); // Fenster wird erzeugt

}}

Die Testprogramme TestFigur2 und TestFigur3 nutzen aus, dass Variablen vom Typder Superklasse auf Objekte der Subklassen verweisen können. Beide Programme be-nötigen deshalb nur eine einzige Variable, die verschiedene Figur-Objekte in einemArray speichert. Für die einzelnen Komponenten des Arrays können die in Figur de-�nierten Methoden unabhängig von der Art des Objektes aufgerufen werden. WelcheImplementierung tatsächlich ausgeführt wird, entscheidet sich erst zur Laufzeit.

18Siehe [Abt02, Gra�sche Benutzerober�ächen].

52

Page 57: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

//Datei: Figuren/TestFigur2.javapublic class TestFigur2{public static void main(String args[]){

Figur [] test = new Figur[3];test [0] = new Rechteck(100,100,40,60);test [1] = new Quadrat(200,200,40);test [2] = new Kreis(300,300,50);for (int i=0; i<test.length ; i++){

System.out.print(test [ i ]. getTyp()+" −−> ");System.out.print(test [ i ]. getPosition ());System.out.print(test [ i ]. getLaengen());System.out.println(" Flaeche: "+test[i ]. getFlaeche());test [ i ]. strecken (1.5);test [ i ]. verscheiben(10,−5);System.out.print(test [ i ]. getTyp()+" −−> ");System.out.print(test [ i ]. getPosition ());System.out.print(test [ i ]. getLaengen());System.out.println(" Flaeche: "+test[i ]. getFlaeche());System.out.println ();

}}

}

//Datei: Figuren/TestFigur3.javaimport java.awt.*;import java.awt.event.*;public class TestFigur3 extends Frame{public void paint (Graphics g){

Figur [] test = new Figur[6];test [0] = new Rechteck(200,100,110,200);test [1] = new Quadrat(225,125,60);test [2] = new Rechteck(310,200,200,100);test [3] = new Rechteck(450,150,30,50);test [4] = new Kreis(280,300,50);test [5] = new Kreis(430,300,50);for (int i=0; i<test.length ; i++){

test [ i ]. zeichnen(g);}

}public TestFigur3(){super("Figuren"); // Titel des FensterssetVisible (true); // Sichtbarkeit des FensterssetSize (800,500); // Groesse des Fensters// aktiviert Button zum Schliessen des FensternaddWindowListener(new WindowAdapter() {public void windowClosing ( WindowEvent e) {System.exit(0);

}});

}public static void main(String args[]){TestFigur3 frame = new TestFigur3();

}}

53

Page 58: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Oberon-2

In Oberon-2 existiert kein Schlüsselwort, um abstrakte Methoden zu kennzeichnen.Sie werden stattdessen mit einem leeren Methodenrumpf deklariert. Wenn eine solcheMethode zur Ausführung gelangt, geschieht einfach nichts. Deshalb ist es besonderswichtig, dass alle abstrakten Methoden in Subklassen überschrieben werden. Dies er-fordert besondere Aufmerksamkeit vom Programmierer, da der Compiler abstrakteMethoden, die nicht überschrieben wurden, nicht als Fehler meldet.Für Figur ist kein Konstruktor de�niert um zu verhindern, dass ein Anwender eineInstanz der Klasse anlegt. Mittels NEW ist es zwar weiterhin möglich, es sollte je-doch vermieden werden, da die abstrakte Klasse keine vollständige Funktionalität zurVerfügung stellt.

(* Datei: Figuren/Figur.mod *)MODULE Figur;IMPORT Out;TYPEFigur* = RECORD

xpos*, ypos* : INTEGER;END;

FigurRef* = POINTER TO Figur;PROCEDURE (f : FigurRef) printTyp*();END printTyp;PROCEDURE (f : FigurRef) printPosition*();BEGINOut.String(" −−> (");Out.Int(f .xpos,4);Out.String(";");Out.Int(f .ypos,4);Out.String(") ");

END printPosition;PROCEDURE (f: FigurRef) printLaengen*();END printLaengen;PROCEDURE (f : FigurRef) printFlaeche*();END printFlaeche;PROCEDURE (f : FigurRef) verschieben*(dx, dy : INTEGER);BEGININC(f.xpos, dx);INC(f.ypos, dy);

END verschieben;PROCEDURE (f : FigurRef) strecken*(faktor : REAL);END strecken;PROCEDURE (f : FigurRef) zeichnen*();END zeichnen;BEGINEND Figur.

54

Page 59: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Die get-Methoden der Klassen Figur, Rechteck, Quadrat und Kreis sind in Oberon-2als print-Methoden implementiert, d.h. die Daten werden von der Methode direkt aufdie Konsole ausgegeben. Für unsere Zwecke genügte diese Variante und man umgehtdie umständliche Verwendung von Zeichenfeldern.Zum Zeichnen der Figuren verwendet zeichnen() Befehle einer Turtle-Gra�k, die imModul MKTurtleLight19 de�niert sind.

(* Datei: Figuren/Rechteck.mod *)MODULE Rechteck;IMPORT Out, Figur, MKTurtleLight;TYPERechteck* = RECORD (Figur.Figur)

breite * , hoehe* : REAL;END;

RechteckRef* = POINTER TO Rechteck;PROCEDURE NEWRechteck*(x, y : INTEGER; breite, hoehe : REAL) : RechteckRef ;VAR tmp : RechteckRef;BEGINNEW(tmp);tmp.xpos := x;tmp.ypos := y;tmp.breite := breite ;tmp.hoehe := hoehe;RETURN tmp;

END NEWRechteck;PROCEDURE (r : RechteckRef) printTyp*();BEGINOut.String("Rechteck");

END printTyp;

PROCEDURE (r : RechteckRef) printLaengen*();BEGINOut.String(" Breite = ");Out.Real(r.breite ,5);Out.String(" Hoehe = ");Out.Real(r.hoehe,5);

END printLaengen;PROCEDURE (r : RechteckRef) printFlaeche*();BEGINOut.String(" Flaeche = ");Out.Real(r.breite*r.hoehe,10);

END printFlaeche;

PROCEDURE (r : RechteckRef) strecken*(faktor : REAL);BEGINr . breite := r . breite*faktor;r .hoehe := r.hoehe*faktor;

END strecken;

19Das Modul MKTurtleLight stammt von M. Kühn und ist unter www.kuehnsoft.de/mkturtle ko-stenfrei erhältlich.

55

Page 60: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

PROCEDURE (r : RechteckRef) zeichnen*();VAR i : INTEGER;BEGIN(* Gehe zum Punkt (r.xpos; r.ypos) *)MKTurtleLight.StiftHoch;MKTurtleLight.Gehe(r.xpos);MKTurtleLight.Drehe(90);MKTurtleLight.Gehe(r.ypos);MKTurtleLight.Drehe(−90);MKTurtleLight.StiftRunter;(* Zeichne Rechteck *)MKTurtleLight.Gehe(r.breite);MKTurtleLight.Drehe(−90);MKTurtleLight.Gehe(r.hoehe);MKTurtleLight.Drehe(−90);MKTurtleLight.Gehe(r.breite);MKTurtleLight.Drehe(−90);MKTurtleLight.Gehe(r.hoehe);MKTurtleLight.Drehe(−90);(* Gehe zum Koordinatenursprung *)MKTurtleLight.StiftHoch;MKTurtleLight.Drehe(−90);MKTurtleLight.Gehe(r.ypos);MKTurtleLight.Drehe(−90);MKTurtleLight.Gehe(r.xpos);MKTurtleLight.Drehe(180);MKTurtleLight.StiftRunter;

END zeichnen;BEGINEND Rechteck.

(* Datei: Figuren/Quadrat.mod *)MODULE Quadrat;IMPORT Out, Figur, MKTurtleLight;TYPEQuadrat* = RECORD (Figur.Figur)

hoehe* : REAL;END;

QuadratRef* = POINTER TO Quadrat;PROCEDURE NEWQuadrat*(x, y : INTEGER; hoehe : REAL) : QuadratRef;VAR tmp : QuadratRef;BEGINNEW(tmp);tmp.xpos := x;tmp.ypos := y;tmp.hoehe := hoehe;RETURN tmp;

END NEWQuadrat;PROCEDURE (q : QuadratRef) printTyp*();BEGINOut.String("Quadrat");

END printTyp;PROCEDURE (q : QuadratRef) printLaengen*();BEGINOut.String(" Hoehe = ");Out.Real(q.hoehe,5);

END printLaengen;PROCEDURE (q : QuadratRef) printFlaeche*();BEGINOut.String(" Flaeche = ");Out.Real(q.hoehe*q.hoehe, 10);

END printFlaeche;

56

Page 61: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

PROCEDURE (q : QuadratRef) strecken*(faktor : REAL);BEGIN

q.hoehe := q.hoehe*faktor;END strecken;PROCEDURE (q : QuadratRef) zeichnen*();VAR i : INTEGER;BEGIN(* Gehe zum Punkt (q.xpos; q.ypos) *)MKTurtleLight.StiftHoch;MKTurtleLight.Gehe(q.xpos);MKTurtleLight.Drehe(90);MKTurtleLight.Gehe(q.ypos);MKTurtleLight.Drehe(−90);MKTurtleLight.StiftRunter;(* Zeichne Quadrat *)FOR i:= 1 TO 4 DOMKTurtleLight.Gehe(q.hoehe);MKTurtleLight.Drehe(−90);

END;(* Gehe zum Koordinatenursprung *)MKTurtleLight.StiftHoch;MKTurtleLight.Drehe(−90);MKTurtleLight.Gehe(q.ypos);MKTurtleLight.Drehe(−90);MKTurtleLight.Gehe(q.xpos);MKTurtleLight.Drehe(180);MKTurtleLight.StiftRunter;

END zeichnen;BEGINEND Quadrat.

(* Datei: Figuren/Kreis.mod *)MODULE Kreis;IMPORT Out, Figur, MKTurtleLight;TYPEKreis* = RECORD (Figur.Figur)

radius * : REAL;END;

KreisRef* = POINTER TO Kreis;PROCEDURE NEWKreis*(x, y : INTEGER; radius : REAL) : KreisRef ;VAR tmp : KreisRef;BEGINNEW(tmp);tmp.xpos := x;tmp.ypos := y;tmp.radius := radius;RETURN tmp;

END NEWKreis;PROCEDURE (k : KreisRef) printTyp*();BEGINOut.String("Kreis");

END printTyp;PROCEDURE (k : KreisRef) printLaengen*();BEGINOut.String(" Radius = ");Out.Real(k.radius,5);

END printLaengen;

57

Page 62: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

PROCEDURE (k : KreisRef) printFlaeche*();BEGINOut.String(" Flaeche = ");Out.Real(3.14*k.radius*k.radius , 10);

END printFlaeche;PROCEDURE (k : KreisRef) strecken*(faktor : REAL);BEGIN

k.radius := k.radius*faktor;END strecken;PROCEDURE (k : KreisRef) zeichnen*();VAR i : INTEGER;

schritt : REAL;BEGIN(* Gehe zum Punkt (k.xpos; k.ypos) *)MKTurtleLight.StiftHoch;MKTurtleLight.Gehe(k.xpos+k.radius);MKTurtleLight.Drehe(90);MKTurtleLight.Gehe(k.ypos);MKTurtleLight.StiftRunter;(* Zeichne Kreis *)schritt := (3.14*k.radius)/180;FOR i:= 1 TO 360 DOMKTurtleLight.Gehe(schritt);MKTurtleLight.Drehe(1);

END;(* Gehe zum Koordinatenursprung *)MKTurtleLight.StiftHoch;MKTurtleLight.Drehe(90);MKTurtleLight.Gehe(k.radius+k.xpos);MKTurtleLight.Drehe(90);MKTurtleLight.Gehe(k.ypos);MKTurtleLight.Drehe(90);MKTurtleLight.StiftRunter;

END zeichnen;BEGINEND Kreis.

Damit die Turtle-Gra�k richtig arbeitet, muss sie zunächst aktiviert werden. Anschlie-ÿend kann die Methode zeichnen() für beliebige Figur -Objekte aufgerufen werden.Nach dem Abarbeiten der Programmbefehle sollte die Turtle wieder deaktiviert wer-den.Von den Klassen Rechteck, Quadrat und Kreis können beliebig viele Instanzen ange-legt werden. Man kann sie sowohl mit einer Variablen jedes eigenen Typs als auch inVariable vom Typ Figur referenzieren. Die Referenztypen der Klassen können als Kom-ponententyp für Arrays genutzt werden. Ein ARRAY n OF Figur.FigurRef kann Ob-jekte der einzelnen Klassen sammeln. Die einzelnen Komponenten werden über einenIndex angesprochen.

58

Page 63: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

(* Datei: Figuren/TestFigur1.mod *)MODULE TestFigur1;IMPORT Out, Figur, Kreis, Quadrat, Rechteck, MKTurtleLight;PROCEDURE ProgMain*();VAR testQ : Quadrat.QuadratRef;

testK : Kreis.KreisRef;i : INTEGER;

BEGIN

MKTurtleLight.TurtleEin;testQ := Quadrat.NEWQuadrat(−350,200,10);testK := Kreis.NEWKreis(50,50,80);FOR i:= 0 TO 18 DOtestQ.zeichnen();testQ.strecken (1.2);testK.zeichnen();testK.verschieben(10,0);

END;MKTurtleLight.TurtleAus;

END ProgMain;BEGINOut.Open

END TestFigur1.

(* Datei: Figuren/TestFigur2.mod *)MODULE TestFigur2;IMPORT Out, Figur, Kreis, Quadrat, Rechteck;PROCEDURE ProgMain*();VAR test : ARRAY 3 OF Figur.FigurRef;

i : INTEGER;BEGINtest [0] := Rechteck.NEWRechteck(100,100,40,60);test [1] := Quadrat.NEWQuadrat(200,200,40);test [2] := Kreis.NEWKreis(300,300,50);FOR i:=0 TO LEN(test)−1 DOtest [ i ]. printTyp();test [ i ]. printPosition ();test [ i ]. printLaengen();test [ i ]. printFlaeche ();Out.Ln;test [ i ]. strecken (1.5);test [ i ]. verschieben(10,−5);test [ i ]. printTyp();test [ i ]. printPosition ();test [ i ]. printLaengen();test [ i ]. printFlaeche ();Out.Ln; Out.Ln;

END;END ProgMain;BEGINOut.Open

END TestFigur2.

59

Page 64: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

(* Datei: Figuren/TestFigur3.mod *)MODULE TestFigur3;IMPORT Out, Figur, Kreis, Quadrat, Rechteck, MKTurtleLight;PROCEDURE ProgMain*();VAR test : ARRAY 6 OF Figur.FigurRef;

i : INTEGER;BEGIN

MKTurtleLight.TurtleEin;test [0] := Rechteck.NEWRechteck(−110,100,110,200);test [1] := Quadrat.NEWQuadrat(−85,75,60);test [2] := Rechteck.NEWRechteck(0,0,200,100);test [3] := Rechteck.NEWRechteck(140,50,30,50);test [4] := Kreis.NEWKreis(−30,−100,50);test [5] := Kreis.NEWKreis(120,−100,50);FOR i:=0 TO LEN(test)−1 DOtest [ i ]. zeichnen();

END;MKTurtleLight.TurtleAus;

END ProgMain;BEGINOut.Open

END TestFigur3.

60

Page 65: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Anhang

A Python-Quellcode

A.1 Beispiel: Konto

Aggregierung, Kapselung und Konstruktor

Python kennt keine begin-end -Klammern. Anweisungsblöcke werden durch dieselbe Einzug-

stiefe gekennzeichnet.

Die Kopfzeile class Klassenname: ist der Beginn einer Klassende�nition. Der Klassenkörper

besteht aus einer oder mehreren eingerückten Anweisungen.

Die __init__-Methode gehört zu einer Menge von Spezialmethoden in Python. Sie wird bei

der Instanzbildung automatisch als Konstruktormethode ausgeführt. Variablen, die innerhalb

dieser Methode initialisiert werden, bilden die Attribute der Klasse.

Methoden werden im Klassenkörper als Funktionen mit dem Schlüsselwort def deklariert. An

den ersten Parameter self wird beim Aufruf automatisch das aufrufende Objekt übergeben.

#Datei: Konto3/Konto.pyw#Beispiel: Aggregierung, Kopplung, Kapselung und Konstruktor# −−> Aggregierungclass Konto:

# −−> Konstruktordef __init__(self, nummer):

# Attriubteself .kontonummer = nummerself .saldo = 0.0

# Methodendef getKontonummer(self):

return self.kontonummerdef getSaldo( self ):

return self.saldodef einzahlen( self , betrag):

self .saldo = self .saldo + betrag # −−> Kopplungdef auszahlen(self , betrag):

self .saldo = self .saldo − betrag # −−> Kopplungdef auszug(self ):

print "Kontonummer: ", self.kontonummer, " Saldo: ", self.saldo, " Euro"

Damit man die de�nierte Klasse in anderen Programmen verwenden kann, muss das zugehö-

rige Modul mittels from Modulname import * importiert werden.

Zur Instanzbildung dient der Klassenname als Funktionsname, um die Konstuktormethode

aufzurufen. Die angegebenen Parameter werden als Initialwerte genutzt.

Python-Module exportieren alle Namen. Es gibt keine Möglichkeit, zu spezi�zieren, welche

Namen auÿerhalb des Moduls nicht sichtbar sein sollen. Datenkapselung ist somit nur ei-

ne Konvention. Der Programmierer kann das Geheimnisprinzip gewährleisten, indem er auf

Datenattribute grundsätzlich nur über Methoden zugreift.

61

Page 66: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

#Datei: Konto3/KontoTest.pyw#Beispiel: Aggregierung, Kopplung, Kapselung und Konstruktorfrom Konto import *meinKonto = Konto(4531088) # Objekt erzeugen und initialisierenmeinKonto.saldo = 200.00 # Zugri� auf Attributeprint "Kontonummer: ", meinKonto.kontonummer, " Saldo: ", meinKonto.saldomeinKonto.einzahlen(300.00) # MethodenaufrufmeinKonto.auszug()deinKonto = Konto(1733065) # neue InstanzdeinKonto.einzahlen(1000.00) # Datenkapselung ist Konventionprint "Kontonummer: ", meinKonto.getKontonummer(), " Saldo: ", meinKonto.getSaldo()deinKonto.auszug()deinKonto.einzahlen(300.00)deinKonto.auszug()

Klassenvariablen

In Python werden Variablen nicht deklariert, sondern durch Zuweisungen de�niert.

Instanzvariablen können nur im Konstruktor erzeugt werden. Alle anderen Variablen, die in-

nerhalb einer Klasse de�niert werden, sind Klassenvariablen. Der Zugri� auf Klassenvariablen

erfolgt über den Namen der Klasse.

#Datei: Konto4/Konto.pyw#Beispiel: Klassenvariablenclass Konto:

zaehler = 0 # −−> Klassenvariabledef __init__(self, nummer):

Konto.zaehler = Konto.zaehler + 1self .kontonummer = nummer # −−> Instanzvariablenself .saldo = 0.0

def getKontonummer(self):return self.kontonummer

def getSaldo( self ):return self.saldo

def einzahlen( self , betrag):self .saldo = self .saldo + betrag

def auszahlen(self , betrag):self .saldo = self .saldo − betrag

def auszug(self ):print "Kontonummer: ", self.kontonummer, " Saldo: ", self.saldo, "Euro"

#Datei: Konto4/KontoTest.pyw#Beispiel: Klassenvariablenfrom Konto import *# Zugri� auf Klassenvariablen ueber Klassennamenprint"Anzahl Konten: ", Konto.zaehlermeinKonto = Konto(4531088)print "Anzahl Konten: ", Konto.zaehlerdeinKonto = Konto(1733065)print "Anzahl Konten: ", Konto.zaehler

62

Page 67: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Manipulierbarkeit

#Datei: Konto5/KontoTest.pyw#Beispiel: Manipulierbarkeitfrom Konto import *def ueberweisen(betrag, kontoA, kontoZ):

kontoA.auszug()kontoZ.auszug()kontoA.auszahlen(betrag)kontoZ.einzahlen(betrag)print "Von Konto ",kontoA.getKontonummer(),print " wurden ",betrag," Euro ",print "auf Konto ",kontoZ.getKontonummer()," ueberwiesen."kontoA.auszug()kontoZ.auszug()

meinKonto = Konto(4531088)meinKonto.einzahlen(300.00)deinKonto = Konto(1733065)deinKonto.einzahlen(100.00)# ZuweisungunserKonto = deinKonto# Vergleichif meinKonto == deinKonto:

print "Mein Konto und dein Konto sind identisch."else:

print "Mein Konto und dein Konto sind verschieden."if unserKonto == deinKonto:

print "Unser Konto und dein Konto sind identisch."else:

print "Unser Konto und dein Konto sind verschieden."# Parameterueberweisen(30.00, meinKonto, deinKonto)

Vererbung

In der Kopfzeile der Klassende�nition kann hinter dem Namen der Klasse in Klammern ange-

geben werden, von welchen Klassen sie abgeleitet wird. Die abgeleitete Klasse erbt dann alle

Attribute und Methoden der Superklasse.

Der Konstruktor wird in der Subklasse neu geschrieben, um weitere Attribute zu ergän-

zen. Die Konstrkutormethode der Superklasse kann man durch den Befehl Superklassenna-

me.__init__(self, ...) aufrufen.

In einem Modul können mehrere Klassen de�niert werden.

# −*− coding: cp1252 −*−#Datei: Konto6/Konto.pyw#Beispiel: Vererbungclass Konto:

zaehler = 0def __init__(self, nummer):

Konto.zaehler = Konto.zaehler + 1self .kontonummer = nummerself .saldo = 0.0

def getKontonummer(self):return self.kontonummer

63

Page 68: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

def getSaldo( self ):return self.saldo

def einzahlen( self , betrag):self .saldo = self .saldo + betrag

def auszahlen(self , betrag):self .saldo = self .saldo − betrag

def auszug(self ):print "Kontonummer: ", self.kontonummer, " Saldo: ", self.saldo, "Euro"

# −−> Vererbungclass Sparkonto(Konto):

# Konstruktor der Klasse Sparkontodef __init__(self, nummer, zins):

Konto.__init__(self, nummer) # Konstruktor der Superklasse Konto wird aufgerufenself . zinssatz = zins # zusaetzliches Attribut

# neue Methoden fuer Zugri� auf Attribut zinssatzdef getZinssatz( self ):

return self . zinssatzdef setZinssatz( self , zins ):

self . zinssatz = zins# neue Methodedef verzinsen( self ):

self .saldo = self .saldo + ( self . zinssatz* self .saldo)/100

Um Objekte der Subklasse zu erzeugen, wird deren Name als Funktionsaufruf verwendet.

Für Instanzen der Subklasse können alle Methoden aufgerufen werden, die in der Superklasse

de�niert sind.

#Datei: Konto6/KontoTest.pyw#Beispiel: Vererbungfrom Konto import *meinSparkonto = Sparkonto(5613990,3.4)# jede Instanz der Klasse Sparkonto hat 3 Attributeprint "Kontonummer: ",meinSparkonto.getKontonummer(), # geerbtes Attributprint " Saldo: ", meinSparkonto.getSaldo(), " Euro", # geerbtes Attributprint " Zinssatz: ", meinSparkonto.getZinssatz() # neu deklariertes Attriubut# Methoden einzahlen(betrag), auszahlen(betrag) und auszug() koennen verwendet werdenmeinSparkonto.einzahlen(250.00) # geerbte MethodenmeinSparkonto.auszug()meinSparkonto.auszahlen(10.00)meinSparkonto.auszug()# ausserdem gibt es fuer Instanzen der Klasse Sparkonto die Methode verzinsen()meinSparkonto.verzinsen() # neu implementierte MethodemeinSparkonto.auszug()

64

Page 69: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Reimplementierung

Wird innerhalb der Subklasse eine Methode der Superklasse mit gleichem Namen und gleicher

Signatur erneut de�niert, dann überschreibt sie die geerbte Methode. Die verdeckte Methode

der übergeordneten Klasse kann über den Namen der Superklasse angesprochen werden.

#Datei: Konto7/Konto.pyw#Beispiel: Reimplementierungclass Konto:

zaehler = 0def __init__(self, nummer):

Konto.zaehler = Konto.zaehler + 1self .kontonummer = nummerself .saldo = 0.0

def getKontonummer(self):return self.kontonummer

def getSaldo( self ):return self.saldo

def einzahlen( self , betrag):self .saldo = self .saldo + betrag

def auszahlen(self , betrag):self .saldo = self .saldo − betrag

def auszug(self ):print "Kontonummer: ", self.kontonummer, " Saldo: ", self.saldo, "Euro"

class Girokonto(Konto):def __init__(self, nummer, limit):

Konto.__init__(self, nummer)if limit < 0 :

limit = −limitself . kreditlimit = limit

# Methode fuer schreibenden Zugri� ueberprueft ob limit positiv istdef getLimit( self ):

if limit < 0 :limit = −limit

return self. kreditlimitdef setLimit( self , limit ):

self . kreditlimit = limit# −−> Reimplementierungdef auszahlen(self , betrag):

if betrag <= self.saldo + self . kreditlimit :Konto.auszahlen(self , betrag)

else:print "Limit ueberschritten!"

65

Page 70: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

#Datei: Konto7/KontoTest.pyw#Beispiel: Reimplementierungfrom Konto import *meinKonto = Konto(4531088)meinKonto.einzahlen(400.00);meinKonto.auszug();print "Versuche 100 Euro abzuheben."meinKonto.auszahlen(100.00); # Methode auszahlen(betrag) der Klasse KontomeinKonto.auszug();print "Versuche 500 Euro abzuheben."meinKonto.auszahlen(500.00); # Methode auszahlen(betrag) der Klasse KontomeinKonto.auszug();print

meinGirokonto = Girokonto(1733065,100)meinGirokonto.einzahlen(400.00);meinGirokonto.auszug();print "Versuche 100 Euro abzuheben."meinGirokonto.auszahlen(100.00); # Methode auszahlen(betrag) der Klasse GirokontomeinGirokonto.auszug();print "Versuche 500 Euro abzuheben."meinGirokonto.auszahlen(500.00); # Methode auszahlen(betrag) der Klasse GirokontomeinGirokonto.auszug();

Polymorphismus

Da Variablen in Python nicht mit einem bestimmten Datentyp deklariert werden, sind alle

Variablen polymorph. Dies bedeutet, dass eine Variable auf Objekte beliebigen Typs verweisen

kann. Python merkt sich während der Ausführungszeit, welche Objektarten ein Programm

benutzt.

#Datei: Konto8/KontoTest.pyw#Beispiel: Polymorphismusfrom Konto import *meinKonto = Konto(4531088) # meinKonto zeigt auf ein Objekt vom Typ KontomeinKonto.einzahlen(300.00)meinKonto.auszug()meinKonto.auszahlen(500.00) # Methode auszahlen(betrag) der Klasse Konto wird aufgerufenmeinKonto.auszug()print

meinKonto = Girokonto(5613990,100) # meinKonto zeigt jetzt auf ein Objekt vom Typ GirokontomeinKonto.einzahlen(300.00)meinKonto.auszug()meinKonto.auszahlen(500.00) # Methode auszahlen(betrag) der Klasse Girokonto wird aufgerufen

# −−> dynamische BindungmeinKonto.auszug()print

meinKonto = Sparkonto(1733065,1.25) # meinKonto zeigt jetzt auf ein Objekt vom Typ SparkontomeinKonto.einzahlen(400.00)meinKonto.auszug()meinKonto.auszahlen(500.00) # Methode auszahlen(betrag) der Klasse Sparkonto wird aufgerufen,

# die sie von der Klasse Konto geerbt hat# meinKonto.verzinsen() Fehler : die Klasse Konto kennt die Methode verzinsen() nicht

Überladen

Das Überladen von Methoden ist in Python nicht möglich.

66

Page 71: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

A.2 Beispiel: Mediendatenbank

# Datei: Medien/Medium.pywclass Medium:

zaehler = 0def __init__(self, titel , preis ):

Medium.zaehler += 1self .code = 100000 + Medium.zaehlerself . titel = titelself . preis = preisself .kommentar = ''

def getCode(self):return self.code

def getTitel( self ):return self. titel

def getPreis( self ):return self. preis

def setPreis( self , preis ):self . preis = preis

def getKommentar(self):return self.kommentar

def setKommentar(self, kommentar):self .kommentar = kommentar

def druckeInfo():print "Code: ", self .codeprint "Titel: " , self . titelprint "Preis: " , self . preis , " Euro"print "Kommentar: ", self.kommentarprint

class Buch(Medium):def __init__(self, titel , autor, verlag , jahr , preis ):

Medium.__init__(self, titel, preis)self .autor = autorself . verlag = verlagself .erscheinungsjahr = jahr

def getAutor(self ):return self.autor

def getVerlag( self ):return self.verlag

def getErscheinungsjahr(self ):return self.erscheinungsjahr

def druckeInfo( self ):print "Code: ", self .codeprint "Titel: " , self . titelprint "Autor: ", self .autorprint "Verlag: ", self . verlag , ", " , self .erscheinungsjahrprint "Preis: " , self . preis , " Euro"print "Kommentar: ", self.kommentarprint

67

Page 72: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

class Cd(Medium):def __init__(self, titel , interpret , titelanz , zeit , preis ):

Medium.__init__(self, titel, preis)self . interpret = interpretself . titelanzahl = titelanzself . spieldauer = zeit

def getInterpret( self ):return self. interpret

def getTitelanzahl( self ):return self. titelanzahl

def getSpieldauer( self ):return self. spieldauer

def druckeInfo( self ):print "Code: ", self .codeprint "Titel: " , self . titelprint "Interpret: " , self . interpretprint "Spieldauer: ", self . spieldauer , " min, ", self . titelanzahl , " Titel"print "Preis: " , self . preis , " Euro"print "Kommentar: ", self.kommentarprint

class Video(Medium):def __init__(self, titel , reg , zeit , preis ):

Medium.__init__(self, titel, preis)self . regisseur = regself . spieldauer = zeit

def getRegisseur( self ):return self. regisseur

def getSpieldauer( self ):return self. spieldauer

def druckeInfo( self ):print "Code: ", self .codeprint "Titel: " , self . titelprint "Regisseur: ", self . regisseurprint "Spieldauer: ", self . spieldauer , " min"print "Preis: " , self . preis , " Euro"print "Kommentar: ", self.kommentarprint

# Datei: Medien/Datenbank.pywfrom Medium import *

class Datenbank:def __init__(self):

self .medien = []def erfasseMedium(self, med):

self .medien.append(med)def au�isten ( self ):

for i in range(0, len( self .medien), 1):self .medien[i ]. druckeInfo()

68

Page 73: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

# Datei: Medien/TestMedienDB.pywfrom Datenbank import *from Medium import *

db = Datenbank()db.erfasseMedium(Buch("Sprechen Sie Java","Hanspeter Moessenboeck", "dpunkt.verlag",2001,28.00))db.erfasseMedium(Cd("No Angel", "Dido", 13, 90, 15.00))db.erfasseMedium(Video("X−Men", "Bryan Singer", 100, 21.00))db. au�isten ()

A.3 Beispiel: Geometrische Figuren

Abstrakte Methoden werden mit Hilfe der pass-Anweisung implementiert. Da der Methoden-

rumpf nicht leer bleiben kann, nutzt man diese leere Platzhalteranweisung, die keine Aktion

bewirkt.

Obwohl die Klasse zu einer abstrakten Klasse wird, wenn sie abstrakte Methoden enthält,

können Instanzen der Klasse erzeugt werden.

# Datei: Figuren/Figur.pywfrom turtle import *class Figur:

def __init__(self,x,y):self .xpos = xself .ypos = y

def getTyp(self):pass

def getPosition( self ):return "(%d;%d)" %(self.xpos, self.ypos)

def getLaengen(self):pass

def getFlaeche( self ):pass

def verschieben( self , dx, dy):self .xpos += dxself .ypos += dy

def strecken( self , faktor ):pass

def zeichnen( self ):pass

class Rechteck(Figur):def __init__(self,x,y,breite,hoehe):

Figur.__init__(self,x,y)self . breite = breiteself .hoehe = hoehe

def getTyp(self):return "Rechteck"

def getLaengen(self):return "Breite = %d Hoehe = %d" %(self.breite, self.hoehe)

69

Page 74: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

def getFlaeche( self ):return self. breite* self .hoehe

def strecken( self , faktor ):self . breite *= faktorself .hoehe *= faktor

def zeichnen( self ):up()goto([ self .xpos, self .ypos])down()forward( self . breite )right(90)forward( self .hoehe)right(90)forward( self . breite )right(90)forward( self .hoehe)right(90)

class Quadrat(Figur):def __init__(self,x,y,hoehe):

Figur.__init__(self,x,y)self .hoehe = hoehe

def getTyp(self):return "Quadrat"

def getLaengen(self):return "Hoehe = %d" %(self.hoehe)

def getFlaeche( self ):return self.hoehe**2

def strecken( self , faktor ):self .hoehe *= faktor

def zeichnen( self ):up()goto([ self .xpos, self .ypos])down()for i in range (0,4,1):

forward( self .hoehe)right(90)

class Kreis(Figur):PI = 3.14def __init__(self,x,y,radius):

Figur.__init__(self,x,y)self .radius = radius

def getTyp(self):return "Kreis"

def getLaengen(self):return "Radius = %d" %(self.radius)

def getFlaeche( self ):return Kreis.PI*self.radius**2

def strecken( self , faktor ):self .radius *= faktor

70

Page 75: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

def zeichnen( self ):schritt = Kreis.PI*self .radius/180up()goto([ self .xpos+self.radius, self .ypos])down()left (90)for i in range (0,360,1):

forward(schritt )left (1)

right(90)

# Datei: Figuren/TestFigur1.pywfrom Figur import *testQ = Quadrat(−150,100,20)testK = Kreis(200,0,80)for i in range (0,15,1):

testQ.zeichnen()testQ.strecken(1.2)

for i in range (0,10,1):testK.zeichnen()testK.verschieben(10,0)

# Datei: Figuren/TestFigur2.pywfrom Figur import *test = [Rechteck(100,100,40,40), Quadrat(200,200,40), Kreis(300,300,50)]for i in range (0,3,1):

print test [ i ]. getTyp()," −−> ",print test [ i ]. getPosition (),print test [ i ]. getLaengen(),print "Flaeche = ", test[i ]. getFlaeche()test [ i ]. strecken(1.5)test [ i ]. verschieben(10,−5)print test [ i ]. getTyp()," −−> ",print test [ i ]. getPosition (),print test [ i ]. getLaengen(),print "Flaeche = ", test[i ]. getFlaeche()

# Datei: Figuren/TestFigur3.pywfrom Figur import *test = []test += [Rechteck(−110,100,110,200)]test += [Quadrat(−85,75,60)]test += [Rechteck(0,0,200,100)]test += [Rechteck(140,50,30,50)]test += [Kreis(−30,−100,50)]test += [Kreis(120,−100,50)]for i in range (0,6,1):

test [ i ]. zeichnen()

71

Page 76: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

B Delphi-Quellcode

B.1 Beispiel: Konto

Aggregierung und Kopplung

Klassen werden in einer Unit beschrieben. Der Name der Unit muss sich dabei vom Klassen-

namen unterscheiden.

Die De�nition der Klasse erfolgt als Typdeklaration, eingeleitet durch das Schlüsselwort type.

Auÿerdem wird mittels Klassenname = class angegeben, dass es sich um eine Klassende�-

nition handelt. In der Klassenbeschreibung müssen die zugehörigen Attribute und Methoden

deklariert werden.

Die Implementierung der Methoden erfolgt gesondert im Implementationsteil der Unit. Für

jede Methode, die deklariert worden ist, muss hier der Methodenrumpf geschrieben werden.

Dabei wird explizit angegeben, zu welcher Klasse die Methode gehört.

{Datei: Konto1/KontoU.pas}{Beispiel : Aggregierung und Kopplung}unit KontoU;interface

{ −−> Aggregierung}type

Konto = classpublic{Attribute}kontonummerF : Integer;saldoF : Double;{Methoden}procedure einzahlen(betrag : Double);procedure auszahlen(betrag : Double);procedure auszug;

end;implementation

{Implementierung der Methoden}procedure Konto.einzahlen(betrag : Double);beginsaldoF := saldoF + betrag {−−> Kopplung}

end;procedure Konto.auszahlen(betrag : Double);beginsaldoF := saldoF − betrag {−−> Kopplung}

end;procedure Konto.auszug;begin

Writeln('Kontonummer: ',kontonummerF,' Saldo: ',saldoF:8:2,' Euro')end;

end.

Das Testprogramm ist eine einfache Konsolenanwendung, die alle notwendigen Units unter

uses importiert.

Variablen werden auÿerhalb des Hauptprogrammes deklariert und müssen später initialisiert

werden.

72

Page 77: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Die Funktion create erzeugt ein Objekt der angegebenen Klasse und liefert dessen Speicher-

adresse als Rückgabewert. Sie wird genutzt, um die deklarierten Variablen mit Werten zu

belegen.

Verweist eine Variable auf eine Instanz einer Klasse, dann können deren Attribute und Me-

thoden über den Namen der Variable angesprochen werden.

{Datei: Konto1/KntoTest.dpr}{Beispiel : Aggregierung und Kopplung}program KontoTest;{$APPTYPE CONSOLE}usesSysUtils ,KontoU in 'KontoU.pas';

var meinKonto, deinKonto : Konto; {Variablen vom Typ Konto}begin

meinKonto := Konto.create; {Objekt vom Typ Konto wird erzeugt}meinKonto.kontonummerF := 4531088; {Zugri� auf Attribute}meinKonto.saldoF := 200.00;Writeln('Konotnummer: ', meinKonto.kontonummerF,' Saldo: ', meinKonto.saldoF:8:2);meinKonto.einzahlen(300.00); {Methodenaufruf}meinKonto.auszug;Writeln;deinKonto := Konto.create; {deinKonto zeigt auf neue Intanz der Klasse Konto}deinKonto.kontonummerF := 1733065;deinKonto.saldoF := 1000.00;deinKonto.auszug;deinKonto.auszahlen(100.00);deinKonto.auszug;Readln

end.

Kapselung

Die Klassende�nition wird in mehrere Bereiche unterteilt. Der erste Teil - gekennzeichnet

durch das Schlüsselwort private - enthält alle Attribute und Methoden, auf die man von an-

deren Units aus nicht zugreifen kann. Sie sind somit gekapselt. Im public-Teil sind diejenigen

Komponenten deklariert, die uneingeschränkt sichtbar sein sollen.

Anstelle der für gekapselte Attribute notwendigen get- und set-Methoden werden in Delphi

Eigenschaften - sogenannte properties - verwendet. Jede Eigenschaft hat einen read - und einen

write-Zweig. Dort können Datenfelder oder Methoden eingetragen werden, die angeben, was

getan wird, wenn der Wert der Eigenschaft gesetzt oder gelesen werden soll. Der write-Zweig

ist optional.

73

Page 78: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

{Datei: Konto2/KontoU.pas}{Beispiel : Kapselung}unit KontoU;interface

typeKonto = class{ −−> Datenkapselung }privatekontonummerF : Integer;saldoF : Double;

publicproperty kontonummer : Integer { Property fuer sicheren Zugri� auf Attibut kontonummerF }read kontonummerF write kontonummerF;

property saldo : Double { Property fuer sicheren Zugri� auf Attribut saldoF }read saldoF write saldoF;

{ urspruengliche Methoden }procedure einzahlen(betrag : Double);procedure auszahlen(betrag : Double);procedure auszug;

end;implementation

procedure Konto.einzahlen(betrag : Double);beginsaldoF := saldoF + betrag

end;procedure Konto.auszahlen(betrag : Double);beginsaldoF := saldoF − betrag

end;procedure Konto.auszug;begin

Writeln('Kontonummer: ',kontonummerF,' Saldo: ',saldoF:8:2,' Euro')end;

end.

Anstelle der Attribute nutzt das Testprogramm die de�nierten Properties, um die Datenfelder

zu initialisieren bzw. zu lesen.

{Datei: Konto2/KontoTest.dpr}{Beispiel : Kapselung}program KontoTest;{$APPTYPE CONSOLE}usesSysUtils ,KontoU in 'KontoU.pas';

var meinKonto : Konto;begin

meinKonto := Konto.create;{ meinKonto.kontonummerF := 4531088; !!FehlerWriteln(meinKonto.kontonummerF); !!Fehler }meinKonto.kontonummer := 4531088; { schreibender Zugri� auf Attribute ueber Properties }meinKonto.saldo := 0.00;Writeln('Kontonummer: ', meinKonto.kontonummer,' Saldo: ', meinKonto.saldo:8:2);Readln

end.

74

Page 79: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Konstruktor

Zur De�nition eines Konstruktors wird das Schlüsselwort constructor vor die Methoden-

deklaration gesetzt. Der Konstruktor heiÿt üblicherweise create. Wie alle anderen Methoden

muss er im Implementierungsteil beschrieben werden.

{Datei: Konto3/KontoU.pas}{Beispiel : Konstruktor}unit KontoU;interface

typeKonto = classprivatekontonummerF : Integer;saldoF : Double;

public{−−> Konstruktor}constructor create(nummer : Integer);property kontonummer : Integerread kontonummerF ; {write entfernt}

property saldo : Doubleread saldoF ; {write entfernt}

procedure einzahlen(betrag : Double);procedure auszahlen(betrag : Double);procedure auszug;

end;implementation

{Implementierung des Konstruktors}constructor Konto.create(nummer : Integer);beginkontonummerF := nummer;saldoF := 0.0;

end;procedure Konto.einzahlen(betrag : Double);beginsaldoF := saldoF + betrag

end;procedure Konto.auszahlen(betrag : Double);beginsaldoF := saldoF − betrag

end;procedure Konto.auszug;begin

Writeln('Kontonummer: ',kontonummerF,' Saldo: ',saldoF:8:2,' Euro')end;

end.

75

Page 80: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

{Datei: Konto3/KontoTest.dpr}{Beispiel : Konstruktor}program KontoTest;{$APPTYPE CONSOLE}usesSysUtils ,KontoU in 'KontoU.pas';

var meinKonto : Konto;begin

{ bisher :meinKonto := Konto.create; // Objekt erzeugenmeinKonto.kontonummer := 4531088; // Kontonummer initialisierenmeinKonto.saldo := 0.00; //Kontostand initialisieren }

{ jetzt : }meinKonto := Konto.create(4531088); {Konstruktor erzeugt Objet und initialisiert Attribute}meinKonto.auszug;Readln

end.

Klassenvariablen

Variablen, die auÿerhalb der Klassende�nition deklariert sind, können als Klassenvariablen

verwendet werden. Sie gehören jedoch zur Unit und nicht zur Klasse, deshalb werden sie

auÿerhalb der Unit über den Unitnamen angesprochen.

{Datei: Konto4/KontoU.pas}{Beispiel : Klassenvariablen}unit KontoU;interface

typeKonto = classprivatekontonummerF : Integer; { −−> Instanzvariablen }saldoF : Double;

publicconstructor create(nummer : Integer);property kontonummer : Integerread kontonummerF ;

property saldo : Doubleread saldoF ;

procedure einzahlen(betrag : Double);procedure auszahlen(betrag : Double);procedure auszug;

end;var zaehler : Cardinal = 0; {−−> Variable der Unit, ersetzt Klassenvariable }implementation

constructor Konto.create(nummer : Integer);beginzaehler := zaehler + 1;kontonummerF := nummer;saldoF := 0.00;

end;

76

Page 81: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

procedure Konto.einzahlen(betrag : Double);beginsaldoF := saldoF + betrag

end;procedure Konto.auszahlen(betrag : Double);beginsaldoF := saldoF − betrag

end;procedure Konto.auszug;begin

Writeln('Kontonummer: ',kontonummerF,' Saldo: ',saldoF:8:2,' Euro')end;

end.

{Datei: Konto4/KontoTest.dpr}{Beispiel : Klassenvariablen}program KontoTest;{$APPTYPE CONSOLE}usesSysUtils ,KontoU in 'KontoU.pas';

var meinKonto, deinKonto : Konto;begin

{ Zugri� auf Klassenvariable ueber Namen der Unit }Writeln('Anzahl Konten: ', KontoU.zaehler);meinKonto := Konto.create(4531088);Writeln('Anzahl Konten: ', KontoU.zaehler);deinKonto := Konto.create(1733065);Writeln('Anzahl Konten: ', KontoU.zaehler);Readln

end.

77

Page 82: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Manipulierbarkeit

{Datei: Konto5/KontoTest.dpr}{Beispiel : Manipulierbarkeit}program KontoTest;{$APPTYPE CONSOLE}usesSysUtils ,KontoU in 'KontoU.pas';

var meinKonto, deinKonto, unserKonto : Konto;procedure ueberweisen(betrag : Double; kontoA, kontoZ : Konto);beginkontoA.auszug;kontoZ.auszug;kontoA.auszahlen(betrag);kontoZ.einzahlen(betrag);Write('Von Konto ',kontoA.kontonummer);Write(' wurden ',betrag:8:2,' Euro ');Writeln('auf Konto ',kontoZ.kontonummer,' ueberwiesen.');kontoA.auszug;kontoZ.auszug

end;begin

meinKonto := Konto.create(4531088);meinKonto.einzahlen(300.00);deinKonto := Konto.create(1733065);meinKonto.einzahlen(100.00);{ Zuweisung }unserKonto := deinKonto;{ Vergleich }if meinKonto = deinKontothen Writeln('Mein Konto und dein Konto sind identisch.')else Writeln('Mein Konto und dein Konto sind verschieden.');if unserKonto = deinKontothen Writeln('Unser Konto und dein Konto sind identisch.')else Writeln('Unser Konto und dein Konto sind verschieden.');{ Parameter }ueberweisen(30.00,meinKonto,deinKonto);Readln

end.

78

Page 83: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Vererbung

Damit die Attribute, Methoden und Eigenschaften der Superklasse in den Subklassen sichtbar

sind, müssen sie public oder protected deklariert werden. Dabei bedeutet protected, dass

man auf diese Komponenten ausschlieÿlich in Subklassen zugreifen kann. In anderen Pro-

grammen oder Klassen sind sie nicht sichtbar. Komponenten die man als private de�niert

sind in der Subklasse nur dann sichtbar, wenn sie sich in der selben Unit be�ndet.

{Datei: Konto6/KontoU.pas}{Beispiel : Vererbung}unit KontoU;interface

typeKonto = classprotectedkontonummerF : Integer; { Attribute sollen vererbt werden }saldoF : Double;

publicconstructor create(nummer : Integer);property kontonummer : Integerread kontonummerF ;

property saldo : Doubleread saldoF ;

procedure einzahlen(betrag : Double);procedure auszahlen(betrag : Double);procedure auszug;

end;var zaehler : Cardinal = 0;implementation

constructor Konto.create(nummer : Integer);beginzaehler := zaehler + 1;kontonummerF := nummer;saldoF := 0.00;

end;procedure Konto.einzahlen(betrag : Double);beginsaldoF := saldoF + betrag

end;procedure Konto.auszahlen(betrag : Double);beginsaldoF := saldoF − betrag

end;procedure Konto.auszug;begin

Writeln('Kontonummer: ',kontonummerF,' Saldo: ',saldoF:8:2,' Euro')end;

end.

Nach dem Schlüsselwort class kann man in Klammern angeben, von welcher Klasse die neue

Klasse abgeleitet wird. Die Subklasse kann in der selben Unit de�niert werden wie die Super-

klasse. Steht die Superklasse in einer anderen Unit, muss diese importiert werden.

Der Konstuktor der Superklasse wird vom Konstruktor der Subklasse verdeckt. Soll er trotz-

dem aufgerufen werden, muss das Schlüsselwort inherited vor dem Methodenaufruf stehen.

79

Page 84: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

{Datei: Konto6/SparkontoU.pas}{Beispiel : Vererbung}unit SparkontoU;interfaceusesSysUtils , KontoU ;

typeSparkonto = class(Konto)privatezinssatzF : Double; { zusaetzliches Attribut }

publicconstructor create(nummer : Integer; zins : Double);{ neue Property fuer den Zugri� auf Attribut zinssatzF }property zinssatz : Doubleread zinssatzF write zinssatzF;

{ neue Methode }procedure verzinsen;

end;implementation

constructor Sparkonto.create(nummer : Integer; zins : Double);begininherited create(nummer); { Konstruktor der Superklasse Konto wird aufgerufen }zinssatzF := zins ;

end;procedure Sparkonto.verzinsen;begin

saldoF := saldoF + (zinssatzF*saldo)/100;end;

end.

{Datei: Konto6/KontoTest.dpr}{Beispiel : Vererung}program KontoTest;{$APPTYPE CONSOLE}usesSysUtils ,KontoU in 'KontoU.pas',SparkontoU in 'SparkontoU.pas';

var meinSparkonto : Sparkonto;begin

meinSparkonto := Sparkonto.create(5613990 , 3.4);{ Jede Instanz der Klasse Sparkonto hat 3 Attribute }Write('Kontonummer: ',meinSparkonto.kontonummer); { geerbtes Attribut }Write(' Saldo: ',meinSparkonto.saldo:8:2,' Euro'); { geerbtes Attribut }Writeln(' Zinssatz: ', meinSparkonto.zinssatz :4:2); { neu deklariertes Attribut }{ Methoden einzahlen(betrag), auszahlen(betrag) und auszug koennen verwendet werden }meinSparkonto.einzahlen(250.00); {geerbte Methoden }meinSparkonto.auszug;meinSparkonto.auszahlen(10.00);meinSparkonto.auszug;{ ausserdem gibt es fuer Instanzen der Klasse Sparkonto die Methode verzinsen }meinSparkonto.verzinsen; { neu implementierte Methode }meinSparkonto.auszug;Readln

end.

80

Page 85: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Reimplementierung

Wird innerhalb der Subklasse eine Methode der Superklasse mit gleichem Namen und gleicher

Signatur erneut de�niert, dann überschreibt sie die geerbte Methode. Auf verdeckte Kompo-

nenten der übergeordneten Klasse kann man durch Verwendung des Schlüsselworts inherited

zugreifen.

Methoden werden in ObjectPascal üblicherweise statisch gebunden, d.h. der Compiler legt

zur Übersetzungszeit fest, welche Implementierung ausgeführt wird. Sollen Methoden wie in

anderen objektorientierten Programmiersprachen dynamisch gebunden werden, so muss dies

durch das Schlüsselwort dynamic expilizit gefordert werden.

{Datei: Konto7/KontoU.pas}{Beispiel : Reimplementierung}unit KontoU;interface

typeKonto = classprotectedkontonummerF : Integer;saldoF : Double;

publicconstructor create(nummer : Integer);property kontonummer : Integerread kontonummerF ;

property saldo : Doubleread saldoF ;

procedure einzahlen(betrag : Double);procedure auszahlen(betrag : Double); dynamic;procedure auszug;

end;var zaehler : Cardinal = 0;implementation

constructor Konto.create(nummer : Integer);beginzaehler := zaehler + 1;kontonummerF := nummer;saldoF := 0.00;

end;procedure Konto.einzahlen(betrag : Double);beginsaldoF := saldoF + betrag

end;procedure Konto.auszahlen(betrag : Double);beginsaldoF := saldoF − betrag

end;procedure Konto.auszug;begin

Writeln('Kontonummer: ',kontonummerF,' Saldo: ',saldoF:8:2,' Euro')end;

end.

Das Schlüsselwort override weist daraufhin, dass diese Methode eine andere Implementierung

überschreibt.

81

Page 86: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

{Datei: Konto7/GirokontoU.pas}{Beispiel : Reimplementierung}unit GirokontoU;interface

usesKontoU;

typeGirokonto = class(Konto)privatelimitF : Double;procedure setLimit(limit : Double);

publicconstructor create(nummer : Integer; limit : Double);property limit : Doubleread limitF write setLimit;

procedure auszahlen(betrag : Double); override;end;

implementationconstructor Girokonto.create(nummer : Integer; limit : Double);begininherited create(nummer);if limit < 0then limit := −limit;limitF := limit ;

end;{ Methode fuer schreibenden Zugri� ueberprueft ob limit positiv ist }procedure Girokonto.setLimit(limit : Double);beginif limit < 0then limit := −limit;limitF := limit

end;{ −−> Reimplementierung }procedure Girokonto.auszahlen(betrag : Double);begin

if betrag <= saldoF + limitFthen inherited auszahlen(betrag)else Writeln('Limit ueberschritten!')

end;end.

{Datei: Konto7/KontoTest.dpr}{Beispiel : Reimplementierung}program KontoTest;{$APPTYPE CONSOLE}usesSysUtils ,KontoU in 'KontoU.pas',GirokontoU in 'GirokontoU.pas';

var meinKonto : Konto;meinGirokonto : Girokonto;

begin

meinKonto := Konto.create(4531088);meinKonto.einzahlen(400.00);meinKonto.auszug;Writeln('Versuche 100 Euro abzuheben.');meinKonto.auszahlen(100.00); { Methode auszahlen(betrag) der Klasse Konto}

82

Page 87: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

meinKonto.auszug;Writeln('Versuche 500 Euro abzuheben.');meinKonto.auszahlen(500.00); { Methode auszahlen(betrag) der Klasse Konto}meinKonto.auszug;Writeln;meinGirokonto := Girokonto.create(1733065,100);meinGirokonto.einzahlen(400.00);meinGirokonto.auszug;Writeln('Versuche 100 Euro abzuheben.');meinGirokonto.auszahlen(100.00); { Methode auszahlen(betrag) der Klasse Girokonto }meinGirokonto.auszug;Writeln('Versuche 500 Euro abzuheben.');meinGirokonto.auszahlen(500.00); { Methode auszahlen(betrag) der Klasse Girokonto }meinGirokonto.auszug;Readln

end.

Polymorphismus

Die Deklaration der Variablen gibt ihren statischen Typ an. Eine Variable kann während der

Ausführungszeit auch auf Instanzen der Subklassen verweisen.

Damit zur Laufzeit die richtigen Aktionen ausgeführt werden, müssen Methoden, die mehrfach

implementiert sind, dynamisch gebunden werden.

{Datei: Konto8/KontoTest.dpr}{Beispiel : Polymorphismus}program KontoTest;{$APPTYPE CONSOLE}usesSysUtils ,KontoU in 'KontoU.pas',SparkontoU in 'SparkontoU.pas',GirokontoU in 'GirokontoU.pas';

var meinKonto : Konto; { Variable vom Typ Konto }begin

meinKonto := Konto.create(4531088); { meinKonto zeigt auf ein Objekt vom Typ Konto}meinKonto.einzahlen(300.00);meinKonto.auszug;meinKonto.auszahlen(500.00); { Methode auszahlen(betrag) der Klasse Konto wird aufgerufen }meinKonto.auszug;Writeln;meinKonto := Girokonto.create(1733065,100); { meinKonto zeigt jetzt auf ein Objekt vom Typ Girokonto}meinKonto.einzahlen(300.00);meinKonto.auszug;meinKonto.auszahlen(500.00); { Methode auszahlen(betrag) der Klasse Girokonto wird aufgerufen }

{ −−> dynamische Bindung }meinKonto.auszug;Writeln;meinKonto := sparkonto.create(1733065,1.25); { meinKonto zeigt jetzt auf ein Objekt vom Typ Sparkonto }meinKonto.einzahlen(400.00);meinKonto.auszug;meinKonto.auszahlen(500.00); { Methode auszahlen(betrag) der Klasse Sparkonto wird aufgerufen, }

{ die sie von der Klasse Konto geerbt hat }meinKonto.auszug;

{ meinKonto.verzinsen; // Fehler: die Klasse Konto kennt die Methode verzinsen() nicht }Readln

end.

83

Page 88: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Überladen

Methoden können mit gleichen Namen, aber unterschiedlichen Signaturen mehrfach innerhalb

einer Klasse deklariert werden. Solche Methoden werden mit dem Zusatz overload versehen.

{Datei: Konto9/KontoU.pas}{Beispiel : Ueberladen}unit KontoU;interface

typeKonto = classprotectedkontonummerF : Integer;saldoF : Double;

public{ bisheriger Konstruktor mit 1 Parameter }constructor create(nummer : Integer); overload;{ weiterer Konstruktor mit 2 Parameter }constructor create(nummer : Integer; betrag : Double); overload ;property kontonummer : Integerread kontonummerF ;

property saldo : Doubleread saldoF ;

procedure einzahlen(betrag : Double);procedure auszahlen(betrag : Double); dynamic;procedure auszug;

end;var zaehler : Cardinal = 0;implementation

constructor Konto.create(nummer : Integer);beginzaehler := zaehler + 1;kontonummerF := nummer;saldoF := 0.00;

end;constructor Konto.create(nummer : Integer ; betrag : Double);beginzaehler := zaehler + 1;kontonummerF := nummer;saldoF := betrag;

end;procedure Konto.einzahlen(betrag : Double);beginsaldoF := saldoF + betrag

end;procedure Konto.auszahlen(betrag : Double);beginsaldoF := saldoF − betrag

end;procedure Konto.auszug;begin

Writeln('Kontonummer: ',kontonummerF,' Saldo: ',saldoF:8:2,' Euro')end;

end.

84

Page 89: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

{Datei: Konto9/SparkontoU.pas}{Beispiel : Ueberladen}unit SparkontoU;interface

uses SysUtils, KontoU ;typeSparkonto = class(Konto)privatezinssatzF : Double;

public{ bisheriger Konstruktor mit 2 Parameter }constructor create(nummer : Integer; zins : Double); overload;{ neuer Konstruktor mit 3 Parameter }constructor create(nummer : Integer; betrag, zins : Double); overload;property zinssatz : Doubleread zinssatzF write zinssatzF;

procedure verzinsen;end;

implementation

constructor Sparkonto.create(nummer : Integer; zins : Double);begininherited create(nummer); { ruft 1−stelligen Konstruktor der Superklasse auf }zinssatzF := zins ;

end;constructor Sparkonto.create(nummer : Integer; betrag : Double; zins : Double);begininherited create(nummer , betrag); { ruft 2−stelligen Konstruktor der Superklasse auf }zinssatzF := zins ;

end;procedure Sparkonto.verzinsen;begin

saldoF := saldoF + (zinssatzF*saldo)/100;end;

end.

{Datei: Konto9/GirokontoU.pas}{Beispiel : Ueberladen}unit GirokontoU;interface

uses KontoU;typeGirokonto = class(Konto)privatelimitF : Double;procedure setLimit(limit : Double);

public{ bisheriger Konstruktor mit 2 Parameter }constructor create(nummer : Integer; limit : Double); overload;{ neuer Konstruktor mit 3 Parameter }constructor create(nummer : Integer; betrag, limit : Double); overload;property limit : Doubleread limitF write setLimit;

procedure auszahlen(betrag : Double); override;end;

implementation

85

Page 90: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

constructor Girokonto.create(nummer : Integer; limit : Double);begininherited create(nummer); { ruft 1−stelligen Konstruktor der Superklasse auf }if limit < 0then limit := −limit;limitF := limit ;

end;constructor Girokonto.create(nummer : Integer; betrag : Double; limit : Double);begininherited create(nummer,betrag); { ruft 2−stelligen Konstruktor der Superklasse auf }if limit < 0then limit := −limit;limitF := limit ;

end;procedure Girokonto.setLimit(limit : Double);beginif limit < 0then limit := −limit;limitF := limit

end;procedure Girokonto.auszahlen(betrag : Double);begin

if betrag <= saldoF + limitFthen saldoF := saldoF − betragelse Writeln('Limit ueberschritten!')

end;end.

{Datei: Konto9/KontoTest.dpr}{Beispiel : Ueberladen}program KontoTest;{$APPTYPE CONSOLE}usesSysUtils ,KontoU in 'KontoU.pas',SparkontoU in 'SparkontoU.pas',GirokontoU in 'GirokontoU.pas';

var meinKonto, deinKonto : Konto;meinSparkonto, deinSparkonto : Sparkonto;meinGirokonto, deinGirokonto : Girokonto;

begin

meinKonto := Konto.create(4531088);meinKonto.auszug;meinKonto.einzahlen(300.00);meinKonto.auszug;Writeln;deinKonto := Konto.create(1733065, 200.00);deinKonto.auszug;deinKonto.einzahlen(300.00);deinKonto.auszug;Writeln;meinSparkonto := Sparkonto.create(5613990,1.25);meinSparkonto.auszug;meinSparkonto.einzahlen(600.00);meinSparkonto.auszug;Writeln;deinSparkonto := Sparkonto.create(7835406,500.0,1.3);deinSparkonto.auszug;

86

Page 91: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

deinSparkonto.einzahlen(600.00);deinSparkonto.auszug;Writeln;meinGirokonto := Girokonto.create(2571183,400.00);meinGirokonto.auszug;meinGirokonto.einzahlen(250.00);meinGirokonto.auszug;Writeln;deinGirokonto := Girokonto.create(6464951,600.00,400.00);deinGirokonto.auszug;deinGirokonto.einzahlen(250.00);deinGirokonto.auszug;Writeln;Readln

end.

B.2 Beispiel: Mediendatenbank

unit MediumU;interfacetypeMedium = classprotectedcodeF : Integer ;titelF : String;preisF : Double;kommentarF : String;

publicconstructor create(titel : String; preis : Double);property code : Integer read codeF;property titel : String read titelF;property preis : Double read preisF write preisF;property kommentar : String read kommentarF write kommentarF;procedure druckeInfo; dynamic;

end;var zaehler : Integer =0;implementation

constructor Medium.create(titel : String; preis : Double);beginzaehler := zaehler +1;self .codeF := 100000 + zaehler;self . titelF := titel ;self .preisF := preis ;self .kommentarF := '';

end;procedure Medium.druckeInfo;beginWriteln('Code: ', self .codeF);Writeln('Titel: ' , self . titelF );Writeln('Preis: ' , self .preisF , ' Euro');Writeln('Kommentar: ', self.Kommentar);Writeln;

end;end.

87

Page 92: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

unit BuchU;interface

uses MediumU;typeBuch = class(Medium)protectedautorF : String;verlagF : String;erscheinungsjahrF : Integer ;

publicconstructor create(titel , autor, verlag : String; jahr : Integer ; preis : Double);property autor : String read autorF;property verlag : String read verlagF;property erscheinungsjahr : Integer read erscheinungsjahrF;procedure druckeInfo; override;

end;implementation

constructor Buch.create(titel, autor, verlag : String; jahr : Integer ; preis : Double);begininherited create( titel , preis );self .autorF := autor;self .verlagF := verlag ;self .erscheinungsjahrF := jahr;

end;procedure Buch.druckeInfo;beginWriteln('Code: ', self .codeF);Writeln('Titel: ' , self . titelF );Writeln('Autor: ', self .autorF);Writeln('Verlag: ', self .verlagF, ' , ' , self .erscheinungsjahrF);Writeln('Preis: ' , self .preisF :6:2, ' Euro');Writeln('Kommentar: ', self.Kommentar);Writeln;

end;end.

unit CdU;interface

uses MediumU;typeCd = class(Medium)protectedinterpretF : String;titelanzahlF : Integer ;spieldauerF : Integer ;

publicconstructor create(titel , interpret : String; titelanz , zeit : Integer ; preis : Double);property interpret : String read interpretF;property titelanzahl : Integer read titelanzahlF;property spieldauer : Integer read spieldauerF;procedure druckeInfo; override;

end;implementation

constructor Cd.create(titel, interpret : String; titelanz , zeit : Integer ; preis : Double);begininherited create( titel , preis );self . interpretF := interpret ;self . titelanzahlF := titelanz ;self .spieldauerF := zeit ;

end;

88

Page 93: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

procedure Cd.druckeInfo;beginWriteln('Code: ', self .codeF);Writeln('Titel: ' , self . titelF );Writeln('Interpret: ' , self . interpretF);Writeln('Spieldauer: ', self .spieldauerF, ' min, ' , self . titelanzahlF , ' Titel ' );Writeln('Preis: ' , self .preisF :6:2, ' Euro');Writeln('Kommentar: ', self.Kommentar);Writeln;

end;end.

unit VideoU;interface

uses MediumU;typeVideo = class(Medium)protectedregisseurF : String;spieldauerF : Integer ;

publicconstructor create(titel , reg : String; zeit : Integer ; preis : Double);property regisseur : String read regisseurF;property spieldauer : Integer read spieldauerF;procedure druckeInfo; override;

end;implementation

constructor Video.create(titel, reg : String; zeit : Integer ; preis : Double);begininherited create( titel , preis );self . regisseurF := reg;self .spieldauerF := zeit ;

end;procedure Video.druckeInfo;beginWriteln('Code: ', self .codeF);Writeln('Titel: ' , self . titelF );Writeln('Regisseur: ', self . regisseurF );Writeln('Spieldauer: ', self .spieldauerF, ' min');Writeln('Preis: ' , self .preisF :6:2, ' Euro');Writeln('Kommentar: ', self.Kommentar);Writeln;

end;end.

unit DatenbankU;interface

uses MediumU;typeDatenbank = classprivatemedien : array of Medium;

publicconstructor create;procedure erfasseMedium(med : Medium);procedure au�isten;

end;implementation

89

Page 94: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

constructor Datenbank.create();beginSetLength(self .medien,0);

end;procedure Datenbank.erfasseMedium(med : Medium);beginSetLength(self .medien, Length(self.medien)+1);self .medien[Length(self.medien)−1] := med;

end;procedure Datenbank.au�isten;var i : Integer ;beginfor i :=0 to Length(self.medien)−1 do

self .medien[i ]. druckeInfo;end;

end.

program TestMedienDB;{$APPTYPE CONSOLE}usesSysUtils ,MediumU in 'MediumU.pas',BuchU in 'BuchU.pas',DatenbankU in 'DatenbankU.pas',CdU in 'CdU.pas',VideoU in 'VideoU.pas';

var db : Datenbank;begindb := Datenbank.create;db.erfasseMedium(Buch.create('Sprechen Sie Java', 'Hanspeter Moessenboeck', 'dpunkt.verlag', 2001, 28.00));db.erfasseMedium(Cd.create('No Angel', 'Dido' , 13, 90, 15.00));db.erfasseMedium(Video.create('X−Men', 'Bryan Singer', 100, 21.00));db. au�isten ;Readln

end.

90

Page 95: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

B.3 Beispiel: Geometrische Figuren

Abstrakte Methoden werden durch das Schüsselwort abstract als solche gekennzeichnet und

im Implementationsteil ausgelassen. Für abstrakte Methoden wird durch virtual erzwungen,

dass sie dynamisch gebunden werden.

{Datei: Figuren/Figur.pas}unit FigurU;interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls;typeFigur = classprotectedxpos, ypos : Integer ;constructor Create(x,y : Integer);

publicfunction getTyp : String; virtual; abstract;function getPosition : String;function getLaengen : String; virtual; abstract;function getFlaeche : Double; virtual; abstract;procedure verschieben(dx, dy : Integer);procedure strecken(faktor : Double); virtual; abstract;procedure zeichnen(can : TCanvas); virtual; abstract;

end;implementation

constructor Figur.create(x,y : Integer );begin

self .xpos := x;self .ypos := y;

end;function Figur.getPosition : String;beginResult := ' ('+IntToStr(self.xpos)+';'+IntToStr(self.ypos)+')';

end;procedure Figur.verschieben(dx, dy : Integer);begin

self .xpos := self .xpos + dx;self .ypos := self .ypos + dy;

end;end.

{Datei: Figuren/RechteckU.pas}unit RechteckU;interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, FigurU;typeRechteck = class(Figur)publicbreite , hoehe : Double;constructor create(x,y : Integer ; b,h : Double);function getTyp : string; override;function getLaengen : String; override;function getFlaeche : Double; override;procedure strecken(faktor : Double); override;procedure zeichnen(canvas : TCanvas); override;

end;

91

Page 96: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

implementation

constructor Rechteck.create(x,y: Integer; b,h : Double);begininherited create(x,y);self . breite := b;self .hoehe := h;

end;function Rechteck.getTyp : String;beginResult := 'Rechteck';

end;function Rechteck.getLaengen : String;beginResult := ' Breite = '+FloatToStr(self.breite)+' Hoehe = '+FloatToStr(self.hoehe);

end;function Rechteck.getFlaeche : Double;beginResult := self . breite * self .hoehe;

end;procedure Rechteck.strecken(faktor : Double);begin

self . breite := self . breite * faktor ;self .hoehe := self .hoehe * faktor;

end;procedure Rechteck.zeichnen(canvas : TCanvas);begincanvas.Rectangle(self .xpos, self .ypos, self .xpos+Round(self.breite), self.ypos+Round(self.hoehe));

end;end.

{Datei: Figuren/QuadratU.pas}unit QuadratU;interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, FigurU;typeQuadrat = class(Figur)protectedhoehe : Double;

publicconstructor create(x, y : Integer ; h : Double);function getTyp : string; override;function getLaengen : String; override;function getFlaeche : Double; override;procedure strecken(faktor : Double); override;procedure zeichnen(canvas : TCanvas); override;

end;implementation

constructor Quadrat.create(x,y : Integer; h : Double);begininherited create(x,y);self .hoehe := h;

end;function Quadrat.getTyp : String;beginResult := 'Quadrat';

end;

92

Page 97: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

function Quadrat.getLaengen : String;beginResult := ' Hoehe = '+FloatToStr(self.hoehe);

end;function Quadrat.getFlaeche : Double;beginResult := self .hoehe * self .hoehe;

end;procedure Quadrat.strecken(faktor : Double);begin

self .hoehe := self .hoehe * faktor;end;procedure Quadrat.zeichnen(canvas : TCanvas);var hoehe : Integer ;beginhoehe := Round(self.hoehe);canvas.Rectangle(self .xpos, self .ypos, self .xpos+hoehe, self.ypos+hoehe);

end;end.

{Datei: Figuren/KreisU.pas}unit KreisU;interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, FigurU;typeKreis = class(Figur)protectedradius : Double;

publicconstructor create(x,y : Integer ; r : Double);function getTyp : string; override;function getLaengen : String; override;function getFlaeche : Double; override;procedure strecken(faktor : Double); override;procedure zeichnen(canvas : TCanvas); override;

end;implementation

constructor Kreis.create(x,y : Integer ; r : Double);begininherited create(x,y);self .radius := r ;

end;function Kreis.getTyp : String;beginResult := 'Kreis' ;

end;function Kreis.getLaengen : String;beginResult := ' Radius = '+FloatToStr(self.radius);

end;function Kreis.getFlaeche : Double;beginResult := 3.14 * self .radius * self .radius;

end;procedure Kreis.strecken(faktor : Double);begin

self .radius := self .radius * faktor ;end;

93

Page 98: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

procedure Kreis.zeichnen(canvas : TCanvas);var radius : Integer ;beginradius := Round(self.radius);canvas.Ellipse ( self .xpos−radius, self .ypos−radius, self .xpos+radius, self .ypos+radius);

end;end.

{Datei: Figuren/TestFigur1U.pas }unit TestFigur1U;interface

usesWindows, Messages, SysUtils, Variants, Classes , Graphics, Controls, Forms,Dialogs , FigurU, RechteckU, QuadratU, KreisU, ExtCtrls;

typeTForm1 = class(TForm)PaintBox1: TPaintBox;procedure PaintBox1Paint(Sender: TObject);

private{ Private−Deklarationen }

public{ Public−Deklarationen }

end;varForm1: TForm1;testQ : Quadrat;testK : Kreis;

implementation

{$R *.dfm}procedure TForm1.PaintBox1Paint(Sender: TObject);var i : Integer ;begintestQ := Quadrat.create(100,100,10);testK := Kreis.create (500,200,80);Canvas.Brush.Style := bsClear;for i := 0 to 18 dobegintestQ.zeichnen(Canvas);testQ.strecken (1.2);testK.zeichnen(Canvas);testK.verschieben(10,0);

end;end;end.

{Datei: Figuren/TestFigur2.dpr}program TestFigur2;{$APPTYPE CONSOLE}usesSysUtils ,FigurU in 'FigurU.pas',RechteckU in 'RechteckU.pas',QuadratU in 'QuadratU.pas',KreisU in 'KreisU.pas';

var test : array [0..2] of Figur;i : Integer ;

94

Page 99: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

begintest [0] := Rechteck.create (100,100,40,60);test [1] := Quadrat.create(200,200,40);test [2] := Kreis.create (300,300,50);for i :=0 to 2 dobeginWrite(test[i ]. getTyp, '−−>');Write(test[i ]. getPosition );Write(test[i ]. getLaengen);Writeln(' Flaeche = ', test[i ]. getFlaeche :8:2);test [ i ]. strecken (1.5);test [ i ]. verschieben(10,−5);Write(test[i ]. getTyp, '−−>');Write(test[i ]. getPosition );Write(test[i ]. getLaengen);Writeln(' Flaeche = ', test[i ]. getFlaeche :8:2);Writeln;

end;Readln;

end.

{ Datei: Figuren/TestFigur3U.pas}unit TestFigur3U;interface

usesWindows, Messages, SysUtils, Variants, Classes , Graphics, Controls, Forms,Dialogs , ExtCtrls, FigurU, RechteckU, QuadratU, KreisU;

typeTForm1 = class(TForm)PaintBox1: TPaintBox;procedure PaintBox1Paint(Sender: TObject);

private{ Private−Deklarationen }

public{ Public−Deklarationen }

end;varForm1: TForm1;test : array [0..5] of Figur;i : Integer ;

implementation

{$R *.dfm}procedure TForm1.PaintBox1Paint(Sender: TObject);begintest [0] := Rechteck.create(200,100,110,200);test [1] := Quadrat.create(225,125,60);test [2] := Rechteck.create(310,200,200,100);test [3] := Rechteck.create (450,150,30,50);test [4] := Kreis.create (280,300,50);test [5] := Kreis.create (430,300,50);for i :=0 to 5 do test[ i ]. zeichnen(Canvas);

end;end.

95

Page 100: Grundkonzepte objektorientierter · PDF fileGrundkonzepte objektorientierter Programmierung - Beispiele in Java, Oberon-2, Python und Delphi Projektarbeit im Studiengang Lehramt Informatik

Literatur

[Abt02] D. Abts: Grundkurs Java. Von den Grundlagen bis zu Datenbank- und Netzanwendungen,3. Au�age, Vieweg, Braunschweig/Weisbaden, 2002.

[Bal99] H. Balzert: Lehrbuch der Objektmodellierung. Analyse und Entwurf,Spektrum Akademischer Verlag, Heidelberg/Berlin, 1999.

[BK03] D. J. Barnes/M. Kölling: Objektorientierte Programmierung mit Java.Eine praxisnahe Einführung mit BlueJ, Pearson Studium, München, 2003.

[BP03] D. Bell/M. Parr: Java für Studenten. Grundlagen der Programmierung,3. überarbeitete Au�age, Pearson Studium, München, 2003.

[C+05] V. Chandrasekhara/A. Eberhart/H. Hellbrück/S. Kraus/U. Walther:Java 5.0. Konzepte, Grundlagen und Erweiterungen in 5.0, Hanser Verlag, Wien, 2005.

[Cla98] U. Claussen: Objektorientiertes Programmieren. Mit Beispielen und Übungen in C++,2. Au�age, Springer Verlag, Berlin/Heidelberg, 1998.

[CH95] C. K. M. Crutzen/H.-W. Hein: Objektorientiertes Denken als didaktische Basis derInformatik, In: [Sch95, S. 149-158].

[Ebn00] M. Ebner: Delphi 5. nachschlagen und verstehen, Addison-Wesley, München, 2000.[ER98] G. Ehmayer/S. Reich: Java in der Anwendungsentwicklung. Objektorientierung, Verteilung,

Datenbanken, dpunkt.verlag, Heidelberg, 1998.[HM99] T. Himstedt/K. Mätzel: Mit Python programmieren. Einführung und Anwendung

skriptorientierter Programmierung, dpunkt.verlag, Heidelberg, 1999.[Kan89] I. Kant: Kritik der reinen Vernunft, Reclam, Stuttgart, 1989.[Lan00] I. van Laningham: Jetzt lerne ich Python. Der schnelle Einstieg in die wunderbare Welt

der Programmierung, Markt+Technik Verlag, München, 2000.[Lis00] R. Lischner: Delphi in a Nutshell. A Desktop Quick Reference, O'Reilly, Sebastopol, 2000.[LS96] A. Lüscher/A. Straubinger: Objektorientierte Technologien. Eine Einführung,

vdf Hochschulverlag, Zürich, 1996.[LA00] M. Lutz/D. Ascher: Einführung in Python, O'Reilly, Köln, 2000.[Mös98] H. Mössenböck: Objektorientierte Programmierung in Oberon-2, 3. Au�age, Springer,

Berlin/Heidelberg/New York, 1998.[Mös01] H. Mössenböck: Sprechen sie Java? Eine Einführung in das systematische Programmieren,

dpunkt.verlag, Heidelberg, 2001.[M+95] J. R. Mühlbacher/B. Leisch/U. Kreuzeder: Programmieren mit Oberon-2 unter Windows,

Carl Hanser Verlag, München/Wien, 1995.[Sch95] S. Schubert (Hrsg.): Innovative Konzepte für die Ausbildung, Springer Verlag, Berlin, 1995.[Wit66] L. Wittgenstein: Tractatus logico-philosophicus. Logisch-philosophische Abhandlung,

Suhrkamp Verlag, Frankfurt a.M., 1966.[Zep04] K. Zeppenfeld: Objektorientierte Programmiersprachen. Einführung und Vergleich

von Java, C++, C#, Ruby, Spektrum Akademischer Verlag, München, 2004.[API1.4] Java 1.4.2 API Dokumentation

http://java.sun.com/j2se/1.4.2/docs/api/index.html (31.07.2006)[API1.5] Java 1.5 API Dokumentation

http://java.sun.com/j2se/1.5.0/docs/api/index.html (31.07.2006)

96