Post on 06-Apr-2015
transcript
ObjektOrientiertes ProgrammierenKonzepte, Begriffe, Beispiele – und ein wenig UML
OOP-Begriffe
AbstraktionReduktion der Wirklichkeit auf das Wesentliche
ModellierenDie Abstraktion in einem Software-Modell beschreiben
UML (Unified Modeling Language)
Standardisierte Art, das Modell in Diagrammen darzustellenFachbereich des Software-Architekten
KlasseBauplan für Objekte
Objekt == Instanz Konkrete Realisierung (Instanziierung) einer Klasse
Attribut == InstanzvariableEigenschaft eines Objekts
MethodeFähigkeit eines Objekts
UML-Klassendiagramm
den Aufbau der einzelnen Klassen dar (wie JavaDoc) stellt Zusammenhänge zwischen Klassen dar
Aufbau von Klassen
Rectangle-length : double-width : double
+setLength(len : double) : void+setWidth(w : double) : void+getLength() : double+getWidth() : double+getArea() : double
Name der Klasse
Attribute der Klasse
Methoden der Klasse
Modifikator+ für public- für private
Typ des Rück-gabewerts
Typ des Über-gabewerts
Zusammenhänge zwischen Klassen
class B extends A { …}
Vererbung
B „ist ein“ A
B „ist Spezialisierung von“ A
class B implements A { …}
Realisierung eines Interface
class A { B b;}
class A { B.init();}
Abhängigkeit
A „hat/benötigt/benutzt“ B
class A { B b;}
gerichtete Assoziation
A „verwendet“ B
class A { B b = new B(this); void xxx() {…} … b.yyy(); … }
class B { A a; public B(A a) { this.a = a; } public yyy() {…} … a.xxx(); …}
bidirektionale Assoziation
A „verwendet“ BB „verwendet“ A
Jede Seite muss eine Referenz der anderen Seite haben. Problem einer Inkonsistenz!
A verwendet B. Wenn B auch A verwendet (indem B auf Datenfelder oder Methoden des Objektes A zugreift), muss B eine Referenz auf das Objekt A haben ("Callback").
class A { B b;}
Komposition
A „hat/besteht aus“ B
B ist ohne A nicht existent und nicht zu benutzen.
s. UM
L-Symbole.doc oder
UM
L/Klassendiagramm
Aufgabe
Zeichnen Sie ein möglichst vollständiges UML-Klassendiagramm des Joe2.0 Szenarios(einschliesslich der benutzten Greenfoot-Klassen)
Ist Greenfoot eher Library oder Framework?
externe Bibliotheke
eine oder mehrere zur Verfügung gestellte Klassen, oft mit internen Abhängigkeiten ( UML)
Es gibt zwei Möglichkeiten (oft gemischt):
1. Eigene Klassen erweitern Fremde (=Framework)class meineKlasse extends fremdeKlasse {}
class meineKlasse implements fremdeKlasse{}
2. Eigene Klassen benutzen Fremde (=Library)import fremdesPaket.fremdeKlasse;
FremdeKlasse xxx = new FremdeKlasse();
Konzepte des OOP
Datenkapselung
Vererbung
Überschreiben
Überladen
Polymorphie
Im Gegensatz
zum prozeduralen
Programmieren
Datenkapselung
ist eines der wichtigsten Grundprinzipien des OOP.
bezeichnet den kontrollierten/eingeschränkten Zugriff auf Methoden bzw. Attribute von Klassen
wird in JAVA durch Zugriffsmodifizierer umgesetzt, die die Sichtbarkeit (und damit Aufrufbarkeit) für externe Klassen kontrollieren: public (öffentlich) von außen für jeden sichtbar private (privat) nur intern (in der Klasse) sichtbar
Datenkapselung
Das Ziel eines sauberen Klassendesigns ist es zu erreichen, dass Klassen bzw. Objekte nur über wenige, wohl-definierte Schnittstellen (= öffentliche Methoden) mit anderen Klassen interagieren.
Vom Innenleben einer Klasse soll der Verwender (Client-Klassen bzw. auch der Programmierer) möglichst wenig wissen müssen (Geheimnisprinzip).
So kann Software maximal modularisiert werden überschaubar, stabil, flexibel & erweiterbar
Regeln für Zugriffsmodifizierer:
Der Zugriff auf Bestandteile einer Klasse sollte immer maximal eingeschränkt werden ("so privat wie möglich").
Instanzvariablen (d.h. Attribute) werden private deklariert. Zugriff von ausserhalb der Klasse erfolgt über public getter- und setter-Methoden. so kann man zwischen Lese- und Schreibrechten
unterscheiden
Konstruktoren werden public deklariert.
Faustregeln für Methoden
keine Methode sollte mehr als 10 Zeilen Code enthalten, sonst in mehrere Aufteilen
jede Methode sollte genau eine Aufgabe haben, dann ist sie auch einfach zu benennen
Gut organisierten Code kann man fast wie normalen Text lesen (dann muss man auch weniger kommentieren)
Methoden sollten möglichst eigenständig sein
Methoden sollten nur dann public sein, wenn es nicht anders geht (= Schnittstellen mit anderen Klassen)
Gründe für Methoden
Code organisieren durch Unterteilung in kleine, wiederverwertbare, eigenständige Einheiten
Code einsparen durch wiederverwendbare Methoden
Code übersichtlich gestalten durch geschickt benannte Methoden
Code flexibel gestalten durch Methoden mit Übergabewerten
Geheimnisprinzip (Sichtbarkeit einschränken)
Vorteile der Datenkapselung
Weniger unerwünschten Interaktionen zwischen Programmteilen, dadurch weniger Bugs
Erhöhte Übersichtlichkeit, da meist nur die öffentliche Schnittstelle einer Klasse (API) betrachtet werden muss
Erhöhte Flexibilität durch Modularität, einzelne Klassen oder Methoden können verändert oder ausgetauscht werden, ohne den Rest des Programms zu beeinflussen.
Vererbung in Java Eine Unterklasse erbt alle Eigenschaften (Attribute und
Methoden) einer Oberklasse.
IST-Beziehung
Beispiel Vererbung
Buntstift erweitert die Funktionalität von Stift (Spezialisierung)
+ ! zeichneKreis
Beispiel Vererbung
class Figurstift extends Buntstift
{
public Figurstift()
{
super(); //Konstruktor der Elternklasse benutzen
}
public void zeichneQuadrat(double s)
{
zeichneRechteck(s, s); //muss auch in Figurstift sein
}
}
Vererbungshierarchie
Wenn man dieselbe Methode in verschiedene Klassen kopiert, ergeben sich Probleme – spätestens wenn man die multiplen Kopien ändern will
Meist hätte man das besser mit Vererbung gelöst, also nur eine Version der Methode in einer gemeinsamen Elternklasse.
Vererbungshierarchie
Alle Klassen erben von Object
"super"
Methode der Oberklasse aufrufen:
super.methodenName();
Normalerweise werden Methoden in Oberklassen automatisch gefunden. super braucht man nur, wenn dieselbe Methode in der eigenen Klasse (this) auch existiert (also überschrieben wurde), man aber diejenige der Oberklasse aufrufen will
Konstruktor der Oberklasse aufrufen:
super();
Da es in allen Klassen immer einen Konstruktor gibt (er also immer überschrieben ist), benötigt man das super() oft, um denn Konstruktor der Oberklasse aufzurufen
"this"
this wird gebraucht, wenn eine Instanz einen Auftrag an sich selber schickt (kann man meist weg lassen), oder wenn die Instanz sich selbst als Parameter übergeben will
onMousePressed(this);
Vorteile der Vererbung
Erhöhte Übersicht in einem Klassendesign Durch die Vererbung lassen sich logische Hierarchien
abbilden
Weniger Quellcode nötig Code der Oberklasse wird in Unterklassen
wiederverwendet
Einfachere Wartung Änderungen müssen nur an einer Stelle durchgeführt
werden
Vorteile der Vererbung (Beispiel)
- name, adresse, telefon müssen nur einmal programmiert werden.- Ein neues Attribut alter muss nur an einer Stelle eingefügt werden.
Überschreiben
wenn Methoden oder Attribute in Kind- UND Elternklasse definiert sind
(die überschriebene Methode kann mit super.f() noch immer aufgerufen werden)
Vorteile des Überschreibens
Im Unterschied zur Vererbung (Erweiterung der Elternklasse) kann man durch Überschreiben Teile des Verhaltens der Elternklasse verändern
Ein Beispiel ist die Methode toString(), die bereits in der grundlegendsten aller Java-Klassen (Object) definiert ist, dann aber in fast allen Unterklassen erneut definiert wird um einen String zu erzeugen, der das Wichtigste
über diese Instanz in druckbarer Form angibt
Überladen
mehrere Versionen einer Methode, die sich nur in Typ und/oder Anzahl der Übergabeparameter unterscheiden
häufig beim Konstruktor eingesetzt
die zum Aufruf passende Version wird vom Compiler automatisch erkannt
Beispiel Überladen
class Figurstift {
Color col;
public Figurstift()
{
col = new Color(255, 0, 0); //default-Wert für col
}
public Figurstift(Color initcol)
{
col = initcol; //bei Erschaffung übergebener Wert //z.B. new Figurstift(new Color(255,0,0));
}
}
Vorteile des Überladens
Implementierung von optionalen Übergabeparametern (default values)
Zeit- und Tipparbeit-Ersparnis beim Gebrauch einer Klasse durch die Definition mehrerer Konstruktoren.
Setzen von Attributen beim Erschaffen der Instanz
Polymorphie (griechisch: Vielgestaltigkeit)
beschreibt die Fähigkeit eines Bezeichners, abhängig von seiner Verwendung unterschiedliche Datentypen anzunehmen.
Jedes Objekt kann auch den Typ seiner Elternklasse(n) annehmen jedes Java-Objekt hat die Grundklasse Object
Objekte können in kompatible Typen gecastet werden, z.B.int i = 1;
double d = (double) i;
Beispiel Polymorphie
public class Polymorphie {
double flaeche = 0;
Rechteck re1 = new Rechteck( 3, 4 );
Figur re2 = new Rechteck( 5, 6 );
Kreis kr1 = new Kreis( 7 );
Figur kr2 = new Kreis( 8 );
Vector vec = new Vector(re1, re2, kr1, kr2);
// Berechne die Summe der Flaechen aller Figuren:
for( int i=0; i<vec.size(); i++ ) {
Figur f = (Figur)(vec.get( i ));
flaeche += f.getFlaeche(); //benutzt die (evtl. über-//schriebene) Methode getFlaeche der jeweiligen Unterklasse
}
System.out.println( "Gesamtflaeche ist: " + flaeche ); }
}
Vorteile von Polymorphie
einheitlicher Aufruf von überschriebenen Methoden (z.B. toString())
dynamische Typumwandlung macht Vererbung erst effizient nutzbar
insgesamt spart man dadurch Tipp- und Organisationsaufwand und bekommt übersichtlicheren Sourcecode