Programmierkurs Kapitel 1 Eigenschaften Objektorientierter

Werbung
Kapitel 1
Objektorientierte Programmierung
Klassen
Methoden
Überladen von Methoden
Der this-Zeiger
Konstruktoren
Vererbung
Attribute von Klassen, Methoden und Variablen
Abstrakte Klassen und Methoden
Interfaces
Programmierkurs
Birgit Engels
Anna Schulze
Zentrum für Angewandte Informatik
Köln
WS 07/08
1 / 58
Eigenschaften Objektorientierter Programmierung
2 / 58
Ziele Objektorientierter Programmierung
Datenkapselung
◮
◮
Daten und die zu diesen Daten gehörende Funktionalität zu
einer Einheit zusammenfassen
Einheiten werden als Objekte bezeichnet
Geringere Komplexität
Übersichtlichkeit
Verringerung des Arbeitsaufwands durch
Vererbung
◮
Eine Klasse kann Eigenschaften einer anderen Klasse erben
◮
Polymorphie
◮
◮
Wiederverwendung vorhandener Klassen
einfache Erweiterung von Klassen
Mehrere gleichnamige Methoden, die sich durch
Argumentenliste unterscheiden
3 / 58
4 / 58
Objektorientierung
Klassische Programmierung versucht stets, einen
Programmablauf zu definieren und diesen in ein Programm
umzusetzen.
Das ist nicht immer die natürliche Betrachtungsweise eines
Problems.
Oft beschreiben Programme Objekte der realen
Welt, wie z.B. einen Drucker:
◮
◮
1.1 Klassen
Ein Drucker ist kein Ablauf, sondern hat bestimmte Daten, die
z.B. seine Eigenschaften beschreiben (Papiergröße,
Papiermenge).
Außerdem gehören zu ihm bestimmte Verfahren, wie gedruckt
wird und wie Einstellungen geändert werden können.
Auch abstrakte Dinge kann man sich als Objekte vorstellen,
z.B. einen Buchungsvorgang bei einer Bank. Daten sind dabei
z.B. Kontonummern von Quelle und Ziel einer Buchung.
5 / 58
Definition einer Klasse
6 / 58
Objekte einer Klasse
public class Auto
{
public String name;
public int erstzulassung;
public class Auto
{
public String name;
public int erstzulassung;
}
public int alter()
{
return 2007 - erstzulassung;
}
}
public int alter()
{
return 2007 - erstzulassung;
}
}
meinKombi ist Variable
vom Typ der Klasse Auto,
ihr wird mit new ein neu erAuto meinKombi;
zeugtes
Objekt zugewiesen
meinKombi = new Auto();
Eine Klassendefinition wird durch das Schlüsselwort class
eingeleitet
Dann folgen in geschweiften Klammern Variablendefinitionen
und Methodendefinitionen
oder
7 / 58
Auto meinKombi = new Auto();
8 / 58
Objekte einer Klasse
Objekte einer Klasse
Der Zugriff auf Variablen und Methoden erfolgt mit
Punktnotation
◮
Auto meinKombi;
meinKombi = new Auto();
◮
Variablen: Objekt.Variable
Methoden: Objekt.Methode(Parameter)
Zuweisung:
Die erste Anweisung ist eine normale Variablendeklaration
Anstelle eines primitiven Typs wird hier der Typname einer
zuvor definierten Klasse verwendet
Die zweite Anweisung gerneriert mit Hilfe des new-Operators
eine neue Instanz der Klasse Auto und weist sie der Variablen
meinKombi zu
meinKombi.name = ‘‘Mercedes 600’’;
meinKombi.erstzulassung = 1972;
Zugriff:
System.out.println(‘‘Name: ’’ + meinKombi.name);
Aufruf von Methoden:
System.out.println(meinKombi.alter());
9 / 58
Objekte sind Referenzen
10 / 58
Objekte sind Referenzen
public class Auto {
{
public String name;
Im Unterschied zu primitiven Datentypen werden Objekte als
Referenz gespeichert.
Die Zuweisung einer Referenz kopiert den Verweis auf das
betreffende Objekt.
Wenn zwei Variablen dieselbe Referenz zugewiesen
bekommen, zeigen diese auf dasselbe Objekt.
public static void main(String[] args) {
Auto meinAuto = new Auto();
Auto meinZweitWagen;
meinZweitWagen = meinAuto;
meinZweitWagen.name = ‘‘BMW’’;
meinAuto.name = ‘‘Käfer’’;
System.out.println(meinZweitWagen.name);
}
}
Was gibt der Algorithmus aus? Die Ausgabe des Algorithmus ist:
Käfer.
11 / 58
12 / 58
Variablen sind keine Referenzen
public class Variablen
{
int a,b;
1.2 Methoden
a = 5;
b = a;
a = 6;
System.out.println(’’b = ’’ + b);
}
Was gibt der Algorithmus aus? Die Ausgabe des Algorithmus ist: b
= 5.
13 / 58
Methoden
14 / 58
Rückgabewert von Methoden
public int alter()
{
return 2007 - erstzulassung;
}
Eine Methode stellt eine Anweisungsliste dar
Sie wird innerhalb einer Klassendefinition angelegt
Sie hat Zugriff auf alle Variablen des Objekts
Globale Funktionen, die vollkommen unabhängig von einem
Objekt oder einer Klasse existieren, gibt es ebensowenig wie
globale Variablen
Später: Klassenvariablen und -methoden, die nicht an eine
konkrete Instanz gebunden sind
Jede Methode ist typisiert
der Typ bestimmt den Typ des Rückgabewerts
Typ kann primitiver Typ, Objekttyp oder vom Typ void sein
Methoden vom Typ void haben keinen Rückgabewert
Rückgabewert wird mit return-Anweisung zurück gegeben:
return Ausdruck;
return-Anweisung führt zum Beenden der Methode
15 / 58
16 / 58
Methoden mit Parametern
Methoden mit Parametern
Alle Parameter werden per call by value übergeben, d.h.
Beim Aufruf der Methode wird aktuelle Wert der Variable in
die Parametervariable kopiert und an die Methode übergeben
Veränderungen der Parametervariablen innerhalb der Methode
bleiben lokal
Im Beispiel wird wieoft nur innerhalb der Methode verändert,
der Aufrufer bemerkt es nicht
public void printalter(String text, int wieoft)
{
while (wieoft-- > 0)
{
System.out.println(text + alter());
}
}
Wie oft wird das Alter von meinKombi in folgendem Beispiel
ausgegeben?
Parameter werden durch Kommata getrennt innerhalb der
Klammern der Methode angegeben
Jeder Parameter besteht aus einem Typnamen und dem
Namen des Parameters
...
int a = 3;
meinKombi.printAlter(a);
meinKombi.printAlter(a);
meinKombi.printAlter(a);
...
17 / 58
18 / 58
Call by value bei Objektvariablen
Objektvariablen sind Referenzen
Bei der Übergabe an eine Methode werden sie per Wert
übergeben, d.h. aber der Wert der Referenz wird übergeben
Veränderung an dem Objekt sind somit auch für den Aufrufer
der Methode sichtbar
call by value für Objektvariablen entspricht call by reference
1.3 Überladen von Methoden
WICHTIG:
Die Übergabe von Objekten an Methoden hat damit zwei wichtige
Konsequenzen:
Die Methode erhält keine Kopie, sondern arbeitet mit dem
Originalobjekt.
Sollen Objekte kopiert werden, so muss dies explizit durch
Aufruf der Methode clone der Klasse Object erfolgen
19 / 58
20 / 58
Überladen von Methoden
Überladen von Methoden
public class Auto
{
public String name;
public int erstzulassung;
public int alter()
{
return 2007 - erstzulassung;
}
public int alter(String titel)
{
int alter = alter();
System.out.println(titel+alter);
return alter;
}
}
Definiere innerhalb einer Klasse zwei unterschiedliche
Methoden mit demselben Namen
Compiler arbeitet mit Signatur einer Methode, die sich aus
dem Namen und über die Reihenfolge und Typen der
Parameter zusammensetzt.
Die Methoden müssen sich in dieser Signatur unterscheiden,
d.h. in der Reihenfolge und/oder Typisierung der Parameter
Beachte: alter wird in drei verschiedenen Bedeutungen verwendet.
21 / 58
22 / 58
Der this-Zeiger
public class ThisExample {
public int x=5;
public int y=10;
public void xPlusy() {
int y=1;
System.out.println(x+this.y);
System.out.println(x+y);
}
public static void main(String[] args) {
ThisExample test = new ThisExample();
test.xPlusy();
}
}
1.4 Der this-Zeiger
23 / 58
Methoden dürfen auf die Variablen ihrer Klasse ohne
Punktnotation zugreifen.
Compiler interpretiert alle nicht lokalen Variablen x ohne
Punktnotation als this.x.
24 / 58
Konstruktoren
Konstruktoren sind Methoden, die bei der Initialisierung eines
Objekts aufgerufen werden
Ein Konstruktor erhält den Namen der Klasse und hat keine
Rückgabewert
public class Auto
{
public String name;
public int erstzulassung;
1.5 Konstruktoren
public Auto(String name)
{
this.name = name;
}
}
25 / 58
Auto dasAuto = new Auto(‘‘Porsche 911’’);
26 / 58
Überladen von Konstruktoren
public Auto(String name)
{
this.name = name;
}
1.6 Vererbung
public Auto(String name, int erstzulassung)
{
this(name);
this.erstzulassung = erstzulassung;
}
Wird ein Konstruktor in einer Methode derselben Klasse
aufgerufen, muss dies als erste Anweisung innerhalb der
Methode geschehen
Sobald ein eigener Konstruktor definiert ist, kann der
default-Konstruktor nicht mehr aufgerufen werden
27 / 58
28 / 58
Vererbung
Zugriff auf vererbte Eigenschaften
Unter Vererbung versteht man die Möglichkeit Eigenschaften
vorhandener Klassen auf neue Klassen zu übertragen
Mit dem Schlüsselwort extends wird die Basisklasse
angegeben
Hierdurch erbt die abgeleitete Klasse alle Variablen und
Methoden der Basisklasse
Besitzt eine Klasse das Attribut final, ist es nicht erlaubt,
eine neue Klasse aus ihr abzuleiten
Cabrio kfz1 = new Cabrio():
kfz1.name = ‘‘MX5’’;
kfz1.erzulassung = 1995;
System.out.println(‘‘Alter = ’’+kfz1.alter());
class Cabrio extends Auto
{
int vdauer;
}
Es kann auf sämtliche Variablen und Methoden der
Basisklasse zugegriffen werden
Die Klasse Cabrio unterscheidet sich von der Klasse Auto nur
dadurch, dass sie zusätzlich die Zeit speichert, die zum Öffnen
der Verdecks benötigt wird.
29 / 58
Verschachtelte Vererbung
30 / 58
Methodenüberlagerung
Die Vererbung kann beliebig tief geschachtelt werden
Geerbte Methoden können neu definiert werden (überlagert
werden)
Es wird immer die überlagernde Version verwendet
class ZweisitzerCabrio extends Cabrio
{
boolean notsitze;
}
class ZweisitzerCabrio extends Cabrio
{
boolean notsitze;
ZweisitzerCabrio kfz1 = new ZweisitzerCabrio();
kfz1.name = ‘‘911-T’’;
public int alter()
{
return 12 * (2007 - erstzulassung);
}
Es kann auf sämtliche Variablen und Methoden der
Basisklasse und auch ihrer geerbten Variablen und Methoden
zugegriffen werden
}
31 / 58
32 / 58
Dynamische Methodensuche
Verhinderung Dynamischer Methodensuche
Nicht immer kann bereits der Compiler entscheiden, welche
Variante einer überlagerten Methode er aufrufen soll
Ein Cabrio-Objekt kann einer Variablen vom Typ Auto
zugewiesen werden
D.h. die Variable vom Typ Auto kann während ihrer
Lebensdauer Objekte verschiedenen Typs enthalten (z.B. vom
Typ Auto, Cabrio, ZweisitzerCabrio
Compiler muss Code generieren, der zur Laufzeit entscheidet
welche überlagerte Methode er benutzt
Das wird als dynamisches Binden bezeichnet
Dies verursacht erheblichen Aufwand an Laufzeit (im
Unterschied zu C/C++)
Um zu verhindern, dass eine Methode dynamisch interpretiert wird,
können folgende Attribute benutzt werden:
Methoden vom Typ private sind in abgeleiteten Klassen
nicht sichtbar und können daher nicht überlagert werden.
Bei Methoden vom Typ final deklariert der Anwender
explizit, dass sie nicht überlagert werden sollen.
Auch bei static-Methoden, die ja unabhängig von einer
Instanz existieren, besteht das Problem nicht
33 / 58
34 / 58
Aufrufen einer verdeckten Methode
Wird eine Methode x in einer abgeleiteten Klasse überlagert,
wird die ursprüngliche Methode x verdeckt
Mit super.x() kann auf die verdeckte Methode zugegriffen
werden
super.super.x() ist nicht erlaubt
Innerhalb des Konstruktors wird mit dem Aufruf super() der
Konstruktor der Basisklasse aufgerufen
Hierbei wird super wie eine normale Methode verwendet und
kann mit oder ohne Parameter aufgerufen werden
1.7 Attribute von Klassen, Methoden und Variablen
35 / 58
36 / 58
Attribute von Klassen, Methoden und Variablen
Sichtbarkeit
Es gibt drei Sichtbarkeitsebenen für den Zugriff auf Elemente einer
Klasse:
public: Elemente des Typs public sind in der Klasse selbst
(also in ihren Methoden), in Methoden abgeleiteter Klassen
und für den Aufrufer von Instanzen einer Klasse sichtbar
protected: Elemente des Typs protected sind in der Klasse
selbst und in den Methoden abgeleiteter Klassen sichtbar. Der
Aufrufer einer Instanz der Klasse kann auf Elemente der
Klasse protected dagegen nur noch dann zugreifen, wenn er
in demselben Paket definiert wurde
private: Elemente des Typs private sind lediglich in der
Klasse selbst sichtbar. Für abgeleitete Klassen und für
Aufrufer von Instanzen bleiben private-Variablen verdeckt
Attribute legen Eigenschaften von Klassen, Methoden und
Variablen fest
Sie haben Einfluß auf die Lebensdauer, Sichtbarkeit und
Veränderbarkeit dieser Programmelemente
Werden Methoden oder Variablen ohne eines der drei
Sichtbarkeitsattribute definiert, so entspricht ihr Verhalten im
wesentlichen dem von Elementen des Typs protected.
37 / 58
Sichtbarkeit
Beispiel zu static- und final-Variablen
static: Variablen und Methoden mit dem Attribut static
sind nicht an die Existenz eines konkreten Objekts gebunden.
◮
◮
38 / 58
public class TestAuto
{
private static int objcnt = 0;
private static final double STEUERSATZ = 18.9;
Eine static-Variable existiert für jede Klasse genau einmal.
D.h. Veränderungen an dieser Variable von einem Objekt sind
für alle anderen Objekte auch sichtbar. (static-Variablen sind
vergleichbar mit globalen Variablen
Das static-Attribut erlaubt bei Methoden den Aufruf, ohne
dass der Aufrufer ein Objekt der Klasse besitzt
public TestAuto()
{
++objcnt;
}
final: Variablen mit dem Attribut final dürfen nicht
verändert werden, sind also als Konstanten anzusehen.
Methoden des Typs final dürfen nicht überlagert werden;
ebensowenig dürfen Klassen des Typs final zur Ableitung
verwendet werden.
}
objcnt zählt die Anzahl der angelegten Objekte
STEUERSATZ ist eine unveränderliche Variable (Konstante), ihr
kann kein neuer Wert zugewiesen werden
Wichtig: Bei final-Methoden kann der Compiler auf dynamisches
Binden verzichten. Deswegen können final-Methoden wesentlich
schneller aufgerufen werden als normale Methoden˙
39 / 58
40 / 58
Abstrakte Klassen und Methoden
Abstrakte Methoden enthalten nur die Deklaration des
Methodenkopfes, aber keine Implementierung des
Methodenrumpfes
Anstelle der geschweiften Klammern steht ein Semikolon
Zusätzlich wird die Definition mit dem Attribut abstract
versehen
Eine Klasse, die eine abstrakte Methode enthält, wird selbst
als abstrakt angesehen und muss mit dem Schlüsselwort
abstract versehen werden
1.8 Abstrakte Klassen und Methoden
abstract class Student
{
String name;
String vorlesungen[];
public abstract void vorlesungen();
}
41 / 58
Abstrakte Klassen und Methoden
42 / 58
Abstrakte Klassen und Methoden
Abstrakte Klassen werden abgeleitet und dort werden eine
oder mehrere abstrakte Methoden implementiert
Eine abstrakte Klasse wird konkret, wenn alle ihre Methoden
implementiert sind
Abstrakte Methoden können nicht aufgerufen werden
Sie definieren nur eine Schnittstelle, die durch Überlagerung in
einer abgeleiteten Klasse implementiert werden kann
Es können keine Objekte von abstrakten Klassen erstellt
werden
public class WIStudent extends Student
{
boolean altstudienordnung;
public void vorlesungen()
{
vorlesungen = new String[1];
vorlesungen[0] = ‘‘Programmierkurs’’;
}
}
43 / 58
44 / 58
Interfaces
In Java nur einfache Vererbung: Eine Klasse kann von
maximal einer anderen Klasse abgeleitet werde
Nicht möglich Mehrfachvererbung: Eine Klasse kann von mehr
als einer anderen Klasse abgeleitet werden
In Java Interfacees
1.9 Interfaces
45 / 58
Interfaces
46 / 58
Verwendung von Interfaces
Die Implementierung eines Interfaces wird durch das
Schlüsselwort implements angezeigt
Es müssen alle Methoden, die im Interface definiert sind,
implementiert werden
Ein Interface ist eine besondere Form einer Klasse
Ein Interface enthält ausschließlich abstrakte Methoden und
Konstanten
Anstelle von class werden zur Definition einen Interfaces die
Schlüsselwörter public interface verwendet
Das Schlüsselwort public ist optional
Alle Methoden sind standardmäßig abstrakt
Ein Interface kann keine Konstruktoren enthalten
public class Auto implements Fortbewegungsmittel
{
public String name;
public double spritVerbrauch;
public interface Fortbewegungsmittel
{
public static final double spritPreis = 1.10;
public double kilometerPreis();
}
public double kilometerPreis()
{
return spritVerbrauch * spritPreis/100;
}
}
47 / 58
48 / 58
Interfaces und Vererbung
Implementieren mehrerer Interfaces
Eine Klasse kann mehrere Interfaces implementieren
Eine Klasse kann sowohl abgeleitet sein als auch ein Interface
implementieren
public interface Sommer
{
...
}
class Cabrio extends Auto implements
Fortbewegungsmittel
{
...
}
class Cabrio extends Auto implements
Fortbewegungsmittel, Sommer
{
...
}
49 / 58
Interfaces sind Klassen
Interfaces besitzen zwei wichtige Eigenschaften, die auch Klassen
haben:
Interfaces lassen sich vererben
Variablen können vom Typ eines Interfaces sein:
◮
◮
Man kann ihnen Objekte zuweisen, die aus Klassen stammen,
die dieses oder eines der daraus abgeleiteten Interfaces
implementieren
Sie können Variablen zugewiesen werden, die zu Klassen
gehören, die dieses Interface implementieren
Deswegen ist folgende Interpretation sinnvoll:
Ein Interface ist eine Typvereinbarung
Eine Klasse, die dieses Interface implementiert, ist dann vom
Typ des Interfaces
Wegen der Mehrfachvererbung von Interfaces kann eine
Instanzvariable damit insbesondere mehrere Typen haben und
zu mehr als einem Typen zuweisungskompatibel sein
51 / 58
50 / 58
Herunterladen