29.06.2015 Aufrufe

8. Programmieren mit Objekten - auf Matthias-Draeger.info

8. Programmieren mit Objekten - auf Matthias-Draeger.info

8. Programmieren mit Objekten - auf Matthias-Draeger.info

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

<strong>8.</strong> <strong>Programmieren</strong> <strong>mit</strong> <strong>Objekten</strong><br />

<strong>8.</strong>1 Objektgeflechte,<br />

<strong>8.</strong>2 Lineare Listen<br />

<strong>8.</strong>3 Spezielle Objekte: Felder<br />

<strong>8.</strong>4 Spezielle Objekte: Zeichenketten


Objektoriente Programmierung<br />

(object oriented progeramming)<br />

besitzt drei Merkmale:<br />

1. Klassenbasierung: Klassentyp fasst Attribute (Felder)<br />

und <strong>auf</strong> den Werten des Typs vorgesehene Operationen<br />

zusammen. Das Sprachkonstrukt heißt Klasse.<br />

2. Datenabstraktion: Operationsschnittstelle (interface)<br />

macht von Implementierung der Methoden und<br />

Repräsentation der Daten als Attribute unabhängig.<br />

Später!<br />

3. Vererbung ("Gemeinsamkeiten von Klassen / <strong>Objekten</strong><br />

ausnutzen")<br />

Später!<br />

hs / fub - alp2-08 2


Beispiel: Bankkunden und ihre Konten<br />

checking<br />

saving<br />

2<br />

owner<br />

owner<br />

public class Account {<br />

public int accNo;<br />

private Customer owner;<br />

private int balance;<br />

public double getBalance() {<br />

return (double) balance;<br />

}...<br />

public void withdraw(…){…}<br />

public void deposit(double amount){<br />

..}<br />

public Account(int accNo,<br />

Customer c){<br />

}<br />

public class Customer {<br />

int custNo;<br />

name long; // encrypted<br />

Account checking, saving;<br />

...}<br />

hs / fub - alp2-08 3


Verkettete Datenstruktur (Geflecht) der Objekte<br />

Customer<br />

Account<br />

c1 = new Customer(...);<br />

c2 = new Customer(...);<br />

c3 = new Customer(...)<br />

c1.checking = new Account(4711,this);<br />

c2.checking = c1.checking;<br />

c2.saving = new Account(553,this);<br />

c3.checking = new Account(6536,this);<br />

c3.saving = new Account(777,this);<br />

public Account(int acc, Customer c){<br />

accNo=acc;<br />

owner = c;<br />

balance = 0;<br />

}<br />

hs / fub - alp2-08 4


Andere mögliche Initialisierungen …<br />

Account acc1= new Account (4711, new Customer(…));<br />

acc11.owner.checking = acc11;<br />

anonym, zeigt<br />

aber in jedem<br />

Fall ein Objekt.<br />

… im Gegensatz zu public Account(int acc, Customer c)<br />

Objektverweis<br />

was kann schief gehen?<br />

hs / fub - alp2-08 5


Rekursiver Datentyp:<br />

Objekt vom Typ K verweist <strong>auf</strong> Objekt vom Typ K (?)<br />

Beispiel: Polygonzug<br />

public class Poly {<br />

private static int<br />

count=0;<br />

Point p;<br />

Poly next;<br />

polyStart =<br />

new Poly(new Point(3,4),<br />

new Poly(new Point(5,10),<br />

new Poly(new Point(10,10),<br />

new Poly (new Point(10,13)null))));<br />

public Poly(Point p,<br />

Poly next);<br />

...<br />

}<br />

Liste wird "von hinten" hinten nach<br />

vorne konstruiert".<br />

hs / fub - alp2-08 6


Vergleich <strong>mit</strong> Listen in funktionalen Sprachen<br />

• Liste als Sprachelement:<br />

Haskell: [5,3,7]<br />

abkürzende Schreibweise für (5:(3:(4:[])))<br />

Konstruktor<br />

"null" (leere Liste)<br />

Elemente vorne an die Liste anfügen:<br />

cons:: a -> [a] -> [a]<br />

cons x liste = (x:liste)<br />

cons identisch <strong>mit</strong> dem<br />

infix-Operator (:)<br />

LISP: cons<br />

• Generische Listen: Basistyp als Parameter ("a")<br />

hs / fub - alp2-08 7


Lineare Liste<br />

public class IList {<br />

final Type head;<br />

final IList tail;<br />

null<br />

Leere Liste<br />

IList (Type x,IList rest){<br />

head = x;<br />

tail = rest;<br />

}<br />

// pre: nichtleere Liste<br />

boolean find(int x){<br />

if (head==x) {return true;}<br />

else {if (tail==null) {return false;}<br />

else {return tail.find(x);}<br />

}<br />

}<br />

... }<br />

"Eine Liste ist leer oder besitzt ein<br />

erstes Element und eine Restliste"<br />

einelementige<br />

Liste<br />

tail: null<br />

head: 3<br />

hs / fub - alp2-08 8


cons lineare Listen<br />

class IList{...<br />

// pre: Liste nicht leer<br />

public IList cons (Type elem){<br />

return (new IList(elem, this));<br />

}...<br />

}<br />

tail:<br />

head: 5<br />

tail:<br />

head: 3<br />

5:(3:(4:[]))<br />

tail: null<br />

head: 4<br />

hs / fub - alp2-08 9


Veränderbare lineare Listen, einfach verkettet <strong>mit</strong> Wächter<br />

null<br />

public class LList {<br />

Node first, last;<br />

null<br />

Liste existiert<br />

nicht (!)<br />

public LList(){<br />

first = new Node();<br />

last = first;<br />

}...<br />

public void insert(Object x){<br />

//vorne Einfügen<br />

first=new Node(x,first);<br />

val: -<br />

next: -<br />

first<br />

} val: o val: -<br />

next next: -<br />

public class Node {<br />

Object val;<br />

Node next;<br />

first last<br />

}<br />

last<br />

leere<br />

Liste<br />

hs / fub - alp2-08 10


Vorteile eines Wächterelements<br />

boolean find (Object o){<br />

last.val = o;<br />

Node ptr=first;<br />

do {<br />

if (ptr.val.equals(o)){<br />

return ptr!=last;}<br />

ptr = ptr.next;<br />

} while (ptr !=last);<br />

// never beyond this point..<br />

return ptr != last;<br />

}<br />

val: x<br />

next<br />

first<br />

val: y<br />

next<br />

Suche negativ ("nicht gefunden") : ptr==last<br />

val: o<br />

next: -<br />

last<br />

Vorteil: keine Sonderfälle zu beachten.<br />

hs / fub - alp2-08 11


Variante: zirkuläre einfach verkettete Liste<br />

last entbehrlich. Ende erreicht, wenn node.next == first<br />

public class CLList {<br />

Node first;<br />

public CLList () {<br />

first.next = last;<br />

}<br />

...<br />

}<br />

Wächterelement am Anfang(?) der<br />

Liste.<br />

Noch mal Konstruktor:<br />

public CLList (Object x) {<br />

this.insert(o);<br />

}<br />

hs / fub - alp2-08 12


Einfügen in lineare zirkuläre Liste <strong>mit</strong> Wächter<br />

Mit dem Knoten-Konstruktor:<br />

public Node(Object x,Node n){<br />

val=x;<br />

next=n;<br />

}<br />

public void insert(Object x){<br />

//insert at front;<br />

first.next=new Node(x,first.next);<br />

}<br />

hs / fub - alp2-08 13


Suchen eines Elements<br />

public boolean find (Object x){<br />

Node ptr=first.next;<br />

while ( ptr!=first) {<br />

if ( ptr.val.equals(x)) {return true;}<br />

else ptr=ptr.next;<br />

}<br />

return false;<br />

}<br />

Leere Liste? <br />

hs / fub - alp2-08 14


Wichtige Variante: Doppelt verkettete zirkuläre Liste<br />

class DLList {…<br />

public DLList(){<br />

head = new Node2();<br />

head.next=head;<br />

head.previous=head;<br />

}<br />

...<br />

}<br />

class Node2{<br />

Object val;<br />

Node2 next, previous;<br />

}<br />

Variable<br />

vom Typ<br />

DLList<br />

hs / fub - alp2-08 15


<strong>8.</strong>2 Felder<br />

Feld (array) a:<br />

Repräsentation der Werte eines Produkttyps T n <strong>mit</strong><br />

beliebigem aber gleichem Basistyp T und beliebiger aber<br />

fester natürlicher Zahl n > 0 .<br />

Java-Spezifika:<br />

- ein Feldtyp wird <strong>mit</strong> T[] bezeichnet.<br />

Bsp: double[] ist ein Feldtyp <strong>mit</strong> Basistyp Float,<br />

Point[] ist Feldtyp <strong>mit</strong> Basistyp Point (!)<br />

- Felder sind Objekte und müssen erzeugt werden.<br />

hs / fub - alp2-08 16


Erzeugung eines Felds<br />

double[] myArray = new double[4];<br />

0.0<br />

0.0<br />

0.0<br />

0.0<br />

myArray[0]<br />

myArray[3]<br />

⇒ Feldvariable hat Verweistyp.<br />

- Indexierte Feldvariable myArray[i] bezeichnet das<br />

i+1-te Feldelement (erstes: myArray[0])<br />

-Typ der Indexmenge: int oder verträglich <strong>mit</strong> int<br />

- Feldelemente werden gemäß Basistyp voreingestellt.<br />

(Autoinitialisierung)<br />

hs / fub - alp2-08 17


Initialisierung..<br />

int[] a = {3,7,2};<br />

… schließt Erzeugung ein.<br />

Man vermutet, dass<br />

vom Übersetzer<br />

initialisiert wird -<br />

<strong>mit</strong>nichten! Also <strong>auf</strong>wändig!<br />

Zuweisung …<br />

int[] b = a;<br />

… erzeugt keine Kopie<br />

Zuweisung…<br />

short[] s={4,6,5};<br />

int[] f = s;<br />

nicht erlaubt, obwohl short <strong>mit</strong> int verträglich.<br />

Warum??<br />

a<br />

b<br />

…<br />

hs / fub - alp2-08 18


Kein Feld:<br />

Point [] pFeld;<br />

null<br />

Leeres Feld:<br />

Point [] pFeld = new Point[0];<br />

Kein leeres Feld<br />

Nicht zu gebrauchen…<br />

Point [] pF = new Point[4];<br />

pF<br />

null nullnull null<br />

Feldelemente sind Objektverweise vom Typ Point.<br />

hs / fub - alp2-08 19


Traversieren von Feldern<br />

int[] f = new int[10];<br />

for(int i = 0; i=<br />

ArrayIndexOutOfBounds<br />

f.length<br />

hs / fub - alp2-08 20


Traversieren (2)<br />

for(int i = 0; i< f.lengthi++) {<br />

if (f[i] > AVG){count++;}<br />

}<br />

kann ersetzt werden durch:<br />

for (int x: f) { //Java 1.5<br />

if (x > AVG){count++;}<br />

}<br />

Nicht immer hilfreich:<br />

for (int x: f) {<br />

x*=2;<br />

} verändert x, nicht f (!)<br />

hs / fub - alp2-08 21


Methoden (nur einige)<br />

Kopieren eines Felds f :<br />

fType a = f.clone();<br />

a enthält Verweis <strong>auf</strong> eine Kopie von f (*)<br />

Diverse Methoden in java.util.Arrays, z.B.:<br />

Vergleich zweier Felder f1,f2 gleichen Typs:<br />

boolean b = equals(f1,f2);<br />

Gleichheit ⇔ gleicher Typ und gleiche Länge und<br />

alle Elemente gleich.<br />

(*) (genauer: eine flache Kopie)<br />

aber das kann man<br />

auch selbst programmieren…<br />

hs / fub - alp2-08 22


<strong>Programmieren</strong> <strong>mit</strong> Feldern (Beispiele)<br />

Gleichheit von Feldern: equals<br />

static public boolean equals (Object[] p, Object[] q ){<br />

if (p==null || q== null) {return false;}<br />

if (p.length != q.length) {return false;}<br />

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

if (p[i] != q[i]){return false;}<br />

}<br />

return true;<br />

}<br />

Verglichen werden Objektverweise, nicht Objekte!<br />

hs / fub - alp2-08 23


Suchen eines Feldelements <strong>mit</strong> Wächter (sentinal):<br />

final int MAX=…;<br />

int[] a = new int[MAX+1] // a[0] bleibt leer!<br />

public boolean find (int n){<br />

a[0] = n;<br />

for (int i = a.length-1; i==0; i--){<br />

if (a[i] == n) return i!=0;<br />

}<br />

return false;<br />

}<br />

hs / fub - alp2-08 24


Polynomauswertung nach Horner:<br />

p n (x) = a n *x n +…+a 1 *x 1 + a 0 = (…( 0*x+a n )*x +a n-1 )*x +…+a 1 )*x +a 0<br />

static double horner (double x, double[] a){<br />

// a != null, a.length = n+1<br />

double p=0;<br />

for (int i=a.length-1; i==0; i--){<br />

p = p*x + a[i];<br />

}<br />

return p;<br />

}<br />

hs / fub - alp2-08 25


Mehrdimensionale Felder<br />

Beispiele:<br />

2D-Matrix : double[][] matrix = new double [100] [100];<br />

Bildpunkte: byte[][] screen = new byte [1280] [1024];<br />

Elementzugriff durch Doppelindex:<br />

for (int z = 0; z < 1280; z ++) {<br />

for (int s = 0; s < 1024; s++) {<br />

screen[z] [s] = (byte)0xff;<br />

}}<br />

hs / fub - alp2-08 26


<strong>8.</strong>4 Zeichenketten<br />

In vielen Programmiersprachen als Feld von Zeichen<br />

realisiert.<br />

Java:<br />

Klassentyp, der Standardtyp der Sprache ist.<br />

String s; ist Verweis (<strong>mit</strong> undefiniertem Wert)<br />

String h = "Hello", w = "world"; //Literale "…"<br />

sind zwei konstante(!) Zeichenketten.<br />

String hw = h+w;<br />

kopiert beide Zeichenketten und fügt die Kopien zusammen,<br />

also neues Zeichenkettenobjekt!<br />

Operation + (Konkatenation) hochgradig überladen.<br />

String s = 3 + "-mal Hello " + "world";<br />

Alle Typen werden in String bewandelt, hier int<br />

hs / fub - alp2-08 27


Beachte:<br />

int[] q = {0,1,2,3,4};<br />

int[] p = {0,1,2,3,4};<br />

boolean b = p==q; // false<br />

String s1 = "Hello";<br />

String s2 = "Hello";<br />

boolean b = s1==s2 // true(!)<br />

s1<br />

s2<br />

Hello<br />

Literal gleiche Strings werden nur<br />

einmal als Konstante gespeichert.<br />

hs / fub - alp2-08 28


Weiteres Besonderheiten … oder auch nicht:<br />

String s1 = "Hello";<br />

String s2 = new String(s1);<br />

boolean b = s1==s2; // false<br />

Hier wird also eine<br />

echte Kopie angelegt!.<br />

String s1;<br />

String s2="";<br />

if (s1!=s2) …;<br />

String s = null;<br />

String t = "";<br />

boolean b = s == t; //false<br />

Fehlermeldung des<br />

Übersetzers: nicht<br />

initialisiert.<br />

Kein Wunder,<br />

wie bei allen<br />

Verweistypen.<br />

hs / fub - alp2-08 29


Viele Operationen <strong>auf</strong> String-<strong>Objekten</strong><br />

(siehe java.lang.String)<br />

s.length()<br />

Länge der Zeichenkette x<br />

s.charAt(i)<br />

Zeichen an Position i<br />

String.valueOf(x)<br />

Zeichenkettendarstellung für beliebigen Typ<br />

(also auch vielfach überladen)<br />

s.toCharArray()<br />

Zeichenkettenfelddarstellung von s<br />

da<strong>mit</strong>:<br />

s.equals(new String(s.toCharArray())<br />

hs / fub - alp2-08 30

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!