Objektorientierte Programmierung mit Java

Document Sample
Objektorientierte Programmierung mit Java Powered By Docstoc
					Objektorientierte Programmierung
             mit Java



       Klassen und Objekte
          Anwendungen
            Interfaces


                                   1
   Server-
                                                 orientierung




Anwendungen
                                                    Objekt-
               Java 2 Software Development Kit




 Datenbanken
  Netzwerke
    Daten
  verwalten
                                                 Prozedurale
   Grafik:



                                                  Elemente
 AWT, Swing
Ein-/Ausgabe
Inhalt
   Wege zu Klassen und Objekten
   Attribute, Methoden und Konstruktoren
   this
   String und StringBuffer
   static oder nicht static?
   Unterklassen, Vererbung und späte Bindung
   cast für Objekte
   Klassen und Ausnahmen
   Interface
   Generische Klassen
   enum
   Dynamische Erzeugung von Objekten
   Autoboxing, Unboxing
   Parameter in variabler Anzahl


                            Prof. Dr. Fritz Jobst   3
Programmieren= Die Welt im Rechner abbilden

   Bisher:
       Gegeben ist ein Problem
       Wir ordnen eine Methode zu
       Evtl. zerlegen wir das Problem in Teilprobleme
   Wo bleiben die Daten?
       Wie wollen wir z.B. eine Person beschreiben?
       Wie wollen wir einen Mitarbeiter beschreiben?
       Wie wollen wir eine Zeichenkette beschreiben?
   Lösung: das Objekt
       Daten und Methoden zur Bearbeitung  Objekt
       Gleichartige Objekte gleichartig behandeln  Klasse


                          Prof. Dr. Fritz Jobst           4
Prof. Dr. Fritz Jobst
Beschreibung der Objekte

   Ein Punkt hat
       Eine x-Koordinate
       Eine y-Koordinate
   Ein Konto hat
       Eine Kontonummer
       Einen Inhaber
       Einen Kontostand
   Eine Person hat
       Einen Namen
       Einen Vornamen


                            Prof. Dr. Fritz Jobst   6
Objekt und Klasse
   Jedes Konto ist ein Objekt, ein Exemplar (Instanz) der
    Klasse Konto
        die Klasse Konto beschreibt Kontos
   Die Kontos sind verschieden: sie unterscheiden sich
    durch Merkmale (Attribute)‫‏‬
        Hierzu brauchen wir die Daten für jedes Exemplar
   Jeder Punkt ist ein Exemplar (Instanz) der Klasse Punkt
        die Klasse Punkt beschreibt Punkte
   Punkte unterscheiden sich durch Merkmale
       Hierzu brauchen wir die Daten (z.B. Koordinaten) für jedes
        Exemplar (Eigenschaften, Attribute)‫‏‬
   Die Behandlung (Methoden) der einzelnen Exemplare
    hängt natürlich mit der Klasse zusammen
       Kontos lassen sich nicht wie Punkte behandeln

                              Prof. Dr. Fritz Jobst                  7
    Wie hat man das Problem früher gelöst?

    Prozedurale Programmierung (PP)‫‏‬
        Datensätze zur Beschreibung der Daten der Objekte (=Dinge)‫‏‬
        Man benutzt irgendwelche Methoden (=Prozeduren) zur
         Verarbeitung der Objekte. Die Methoden erhalten die Daten z.B.
         als Parameter übergeben: Methode(Objekt);
    Objektorientierte Programmierung (OOP)‫‏‬
        Daten (=Attribute) + Methoden bilden eine Einheit.
        Attribute müssen nicht mehr übergeben werden, sondern:
        Wende die Methode auf das Objekt an: Objekt.Methode();
        Oder: sende dem Objekt die Botschaft "Methode"
   Vorsicht
        Man sollte keine Methoden für Punkte auf ein Konto anwenden!
        Zusätzlich gibt es die Kapselung, siehe nächste Folien...



                                Prof. Dr. Fritz Jobst                   8
In Java (Codefragment)‫‏‬
  public class Konto {
    private String name; // PRIVAT!!!!!!
    private int stand;   // PRIVAT!!!!!!
      // get+set für Attribute
      public void setName (String name) {...}
      public String getName (){...}
      // Die Methode abheben
      public int abheben (int betrag) { ...}
      }
  }



                   Prof. Dr. Fritz Jobst   9
Prof. Dr. Fritz Jobst
Prof. Dr. Fritz Jobst
Kapselung: Eigenschaften und Zustand
   Die Kapselung stellt sicher, dass der Zustand
    eines Objekts nur über die in der Schnittstelle
    spezifizierten Eigenschaften verändert wird.
   Der Stand des Kontos kann nicht einfach gesetzt
    werden, aber es darf eingezahlt bzw. abgehoben
    werden.
   Dabei kann man die Beträge überprüfen.
       Einzahlung negativer Beträge  abbrechen
       Überschreiten Dispo-Limit  Auszahlung verweigern
       Protokollieren von Änderungen Kontoauszug


                         Prof. Dr. Fritz Jobst         12
Objektidentität OID
   OID = „Hausnummer“ des Objekts, nicht das
    Objekt!
   Das Objekt selber liegt auf dem Heap-Speicher.
   Objekt-Variable speichern OIDs, keine Objekte
   OIDs ermöglichen gemeinsame Nutzung von
    Objekten
   In C++ und Java:
       OID ist der Zeiger auf den Speicherplatz für das
        Objekt, die Referenz.
       Dies gilt nicht für Objekte in fremden Prozessen oder
        fremden Rechnern (Verteilte Systeme)‫‏‬


                          Prof. Dr. Fritz Jobst           13
Klassen in Java
   Klassen können sowohl auf der Ebene des
    Hauptprogramms als auch innerhalb von
    anderen Klassen als geschachtelte Klassen
    definiert werden.
   Jede Datei darf höchstens eine Klasse mit dem
    public-Attribut enthalten.
   Diese Klasse muss den Namen der Datei (ohne
    den Zusatz .java) haben.
   Die Definition einer Klasse besteht aus
    verschiedenen Komponenten:


                     Prof. Dr. Fritz Jobst      14
Eine Klasse hat:
   Attribut(e):
       Datenfelder bzw. Variable für die speziellen Eigenschaften der
        Objekte
   Methode(n):
       Bearbeitung der Daten, Bereitstellen von Diensten
   Konstruktor(en):
       Spezielle Methoden ausschließlich zur Initialisierung
       Die Objekte müssen vor Gebrauch eingerichtet werden
   Zugriffskontrolle (Kapselung):
       public:    alle dürfen zugreifen
       private:   nur aus dieser Klasse zugreifen
       protected: nur abgeleitete Klassen dürfen zugreifen



                              Prof. Dr. Fritz Jobst                  15
Eine Klasse Person
public class Person {
 // Die Attribute einer Person im Betrieb.
 private String name;

 private int personalNummer;

 private double gehalt;

 public Person(String name, int personalNummer,
               double gehalt) {
   this.gehalt = gehalt;
   this.name = name;
   this.personalNummer = personalNummer;
 }

                        Prof. Dr. Fritz Jobst     16
Methoden für Personen
 // Methode zur Selbstdarstellung
 public void drucke() {
     System.out.printf(
        "Name = %-10s Personalnummer = %3d Gehalt = %7.2f\n",
         name, personalNummer, gehalt);
 }
 // Diese Methode sollte der Chef öfter anwenden…
 public void erhoeheGehalt(double Betrag) {
   gehalt += Betrag;
 }
 public double getGehalt() {
   return gehalt;
 }
 public String getName() {
   return name;
 }
 public int getPersonalNummer() {
   return personalNummer;
 }                      Prof. Dr. Fritz Jobst                   17
Abläufe aus main
    public static void main(String[] args) {
      Person alfred   = new Person("Hitchcock", 0, 1000);
      Person james    = new Person("Bond",      7, 2000);
      Person harrison = new Person("Ford",     99, 3000);

        alfred.drucke(); // drucke()-Auftrag an alfred
        james.drucke(); // drucke()-Auftrag an james
        harrison.drucke(); // drucke()-Auftrag an harrison

        // alfreds Gehalt wird erhöht
        alfred.erhoeheGehalt(4000);
        alfred.drucke(); // drucke()-Auftrag an alfred

        // Einer neuen Person einen drucke()-Auftrag erteilen.
        new Person("Streep", 10, 6000).drucke();
    }
}


                              Prof. Dr. Fritz Jobst              18
Darstellung in UML
   Unified Modeling                   Person

    Language                           -name :String
                                       -personalNummer :int
   Notiere den Namen, die             -gehalt :double

    Attribute sowie die                +main(String[]):void
                                       +getName():String
    Operationen                        +drucke():void
                                       +erhoeheGehalt(double):void

    + = public,
                                       +getGehalt():double
                                      +getPersonalNummer():int

   - = private,
   # = protected
   http://www.uml.org/




                        Prof. Dr. Fritz Jobst                        19
Prof. Dr. Fritz Jobst
Anlegen von Exemplaren: new
   Klassenname exemplarname =
             new Klassenname (Argument1, usw.);

   Klassenname exemplarname;
   // Hier kein Zugriff exemplarname.xyz möglich!!.
   exemplarname = new Klassenname (Argument1, usw);
   Andere Ausdrucksweisen:
       Erzeugen von Objekten
       Erzeugen von Instanzen
       Erzeugen von Exemplaren
   Die Variable exemplarname wird mit dem OID
    belegt (z. B. eine Referenz auf den Inhalt des
    Objekts)‫‏‬

                        Prof. Dr. Fritz Jobst        21
Konstruktoren
   Ein Konstruktor ist eine spezielle Methode, wobei gilt
       Methodenname gleich Klassenname.
   Jede Klasse legt durch Konstruktoren fest, wie Objekte
    von ihr erzeugt werden können.
   Eine Parameterliste mit Initialisierungswerten kann in
    runden Klammern aufgeführt werden ().
   Falls kein einziger Konstruktor angegeben wird, dann
    legt Java im pCode einen sog. Default-Konstruktor ohne
    Parameter an.
   Meist ist der Konstruktor public, damit andere Klassen
    Exemplare der Klasse erzeugen können.



                           Prof. Dr. Fritz Jobst             22
this
   In einem Objekt kann mit this Bezug auf sich
    selbst (d.h. das aktuelle Objekt, in anderen
    Sprachen: self) genommen werden.
   this enthält den Objektidentifizierer OID für das
    aktuelle Objekt.
   Beispiel: eine Alternative im Konstruktor Person
// Ein Konstruktor: Ersteinrichtung des Exemplars
    public Person (String name,
                   int personalNummer,
                   double gehalt) {
      this.name           = name;
      this.personalNummer = personalNummer;
      this.gehalt         = gehalt;
    }

                       Prof. Dr. Fritz Jobst        23
Wertzuweisung für Objekte
   Der Unterschied zwischen einem Objekt und
    seiner OID (=Hausnummer) ist zu beachten.
   Damit können Objekte auch als Parameter bei
    Methodenaufrufen übergeben werden.
   Dies ist stets die Übergabe der OID!!
   Auch eine Rückgabe eines Objekts aus einer
    Methode erfolgt durch Liefern der OID.




                     Prof. Dr. Fritz Jobst        24
Prof. Dr. Fritz Jobst
Lebensdauer von Objekten
   Wir erzeugen Objekte mit Person p = new Person(…).
   Danach ist das Objekt über die Referenz p ansprechbar.
   Das Person-Objekt bleibt solange erhalten, wie der Wert
    der Referenz „erreichbar“ ist.
       D.h.: der Wert ist irgendwo in einem der Datenbereiche
        enthalten: lokale Variable von Methoden, deren Aufruf nicht
        beendet ist, globale Daten.
   Wenn ein Objekt nicht mehr erreichbar ist, kann man es
    nicht mehr benutzen, es kann freigegeben werden.
   Die Freigabe von Exemplaren wird in Java von der sog.
    Garbage-Collection System.gc () übernommen.
       (Müllabfuhr, Speicherbereinigung)‫‏‬
   Vorsicht:
       Man weiß nie, wann die „Müllabfuhr“ kommt. Wenn die Garbage-
        Collection läuft, dann können Programme unterbrochen werden.


                              Prof. Dr. Fritz Jobst                   26
Lebensdauer von Objekten
   Referenzen auf null setzen
       Wenn eine Referenz nicht mehr benötigt wird, sollte man diese auf null
        setzen.
            Person p = new Person (…);
            ….
            p = null;
       Damit verschwindet an dieser Stelle der Bezug zu dem Objekt.
       Wenn die letzte OID eines Objekts erlischt, dann darf die Garbage-
        Collection das Objekt entsorgen.
   finalize()‫‏‬
         protected void finalize() throws Throwable
           {
           super.finalize();
           }
       finalize wird vom java-Laufzeitsystem vor der Entsorgung
        aufgerufen, um abschließende Arbeiten durchzuführen (z.B.
        Verbindungen abbauen etc…)‫‏‬
       Wenn finalize die OID des Objekts wieder irgendwo abspeichert,
        dann kann das Objekt nicht mehr entsorgt werden.
       Vgl. Java Language Spec., 2nd Edition
       In anderen Sprachen als “Destruktor” bekannt
                                Prof. Dr. Fritz Jobst                        27
Zeichenketten in Java
   Die Klasse String dient der Programmierung von
    Zeichenketten.
       String s = "abc";
       // oder gleichwertig, aber genauer:
       String s = new String ("abc");
   String-Objekte werden meistens in der bequemen 1.
    Schreibweise angesprochen.
   Für String-Objekte gibt es den bequemen Operator +
       String t = s1 + s2;
   Dadurch wird der Inhalt der Strings s1 und s2 verkettet
    und im durch t bezeichneten String abgelegt.



                         Prof. Dr. Fritz Jobst           28
String-Objekte
   Der Inhalt von String-Objekten ist unveränderlich.
   String s = "hello";
   s = s + "world"; // (*)‫‏‬
   Durch (*) wird auf der rechten Seite eine neue
    Zeichenkette angelegt.
       "helloworld"
   Die Adresse der neuen Zeichenkette (OID) wird der
    Variablen s wieder zugewiesen.
   Die verschiedenen JDK-Versionen in der Java-
    Laufzeitmaschine versuchen, jede Zeichenkette nur
    einmal abzulegen.



                         Prof. Dr. Fritz Jobst           29
Methoden der Klasse String
   Siehe http://java.sun.com/j2se/1.5/docs/api/
   Kurzform: s, t: Strings. Indices immer ab 0.

       char t.charAt(int x);
           liefert das Zeichen an der Stelle x im String. Erstes Zeichen
            für x=0. Aber nur, falls vorhanden!
       boolean t.equals(String s);
           true genau bei Gleichheit von s und t
       int t.length();
           liefert die Länge des Strings zurück
       String t.substring(int x, int y);
           liefert den String von Pos. x bis Pos. y zurück



                               Prof. Dr. Fritz Jobst                   30
Methoden der Klasse String
     String t.toLowerCase()‫‏‬
         Liefert einen String, der aus allen in Kleinbuchstaben
          umgewandelten Zeichen von t besteht.
     String t.toUpperCase()‫‏‬
         Liefert einen String, der aus allen in Großbuchstaben
          umgewandelten Zeichen von t besteht.
      int t.indexOf(x);
         x = Zeichen bzw. Substring
         Sucht die erste Stelle, an der das Zeichen oder der Substring
          x auftritt




                             Prof. Dr. Fritz Jobst                 31
Die Klasse StringBuffer
   Die Klasse dient zum Aufbau von Zeichenketten.
   Im Gegensatz zu Strings kann sich der Inhalt ändern.
   Anwendung: Aufbau von Strings aus mehreren Teilen
       b ein StringBuffer
       b.append (x);
            Anhängen der Textform von x an b
       b.insert (int offset, x);
            Einsetzen der Textform von x in b
       char b.charAt(int x);
            liefert das Zeichen von b an der Stelle x
       String b.toString();
            Liefere einen String mit dem Inhalt des StringBuffers b




                                  Prof. Dr. Fritz Jobst                32
Beispiel
   Eine Methode soll eine Zahl mit einer bestimmten Anzahl von Ziffern
    rechtsbündig ausgeben.
     static String z2T (
       int zahl, int AnzahlZiffern) {
         // In b wird die Zeichenfolge zusammengebaut
         StringBuffer b = new StringBuffer ();

         b.append (zahl);
         while (b.length() < AnzahlZiffern)‫‏‬
           b.insert (0, ' ');

         // Liefere einen String
         return b.toString ();
     }
   Beispiele:
      k03/src/TestSerialisierung.java

      k03/src/SerialisierungDemo.java




                             Prof. Dr. Fritz Jobst                 33
Flache Kopie, tiefe Kopie
   Bei der Wertzuweisung a = b für Objekte werden nicht
    die Inhalte eines Objekts, sondern nur Adressen kopiert.
   Bei der Kopie eines Objekts müssen die Inhalte, also alle
    Attribute, kopiert werden.
   Auch hier stellt sich die Frage: Werden nur die Werte
    oder die Inhalte kopiert?
   Falls nur die Werte der Attribute kopiert werden, spricht
    man von einer flachen Kopie.
   Falls die Attribute ihrerseits wieder Referenzen auf
    Objekte sind, müsste man die obige Überlegung wieder
    anstellen.
   In diesem Fall spricht man von einer tiefen Kopie.
   Beispiel: k03/src/Wertzuweisung.java
                         Prof. Dr. Fritz Jobst            34
static:Klassen-Variablen und -Methoden
   Variablen bzw. Methoden, die nur einmal pro Klasse
    existieren.
       Ansprechen: Klassenname.name
       Verarbeiten klassenspezifischer Daten
       Unabhängig von der Erzeugung von Objekten!
       Nur einmal pro Klasse vorhanden
       Können keine Objekt-Variablen oder Methoden ohne Bezug zu
        einem Objekt verwenden.
   Anwendung (z.B.)‫‏‬
       Für allgemeine Methoden, z.B. java.lang.Math-Bibiliothek.
            Mathematik-Routinen: double x = Math.sin (…);
       Für Konstanten: Color.red.
       Als Zähler für Exemplare (Objekte) von Klassen.
       Wiederauferstehung der globalen Variablen in neuem Gewand.


                             Prof. Dr. Fritz Jobst              35
Speicherzuordnung
   Objekte liegen in Java grundsätzlich im dynamischen
    Speicher, dem sog. Heap-Speicher.
   Die Variablen von Methoden liegen auf dem
    Laufzeitstack. Dies können „gewöhnliche“ Werte wie int-
    Variable oder OIDs sein.
   static-Variable einer Klasse können nicht im Objekt
    abgespeichert werden, da sie unabhängig von
    irgendwelchen Objekten einer Klasse existieren.
   Dies gilt auch für den Programmcode der Methoden.
   Damit ergeben sich drei grundsätzlich verschiedene
    Typen des Speichers:
       Stack, dynamischer Speicher, statischer Speicher


                              Prof. Dr. Fritz Jobst        36
public class Gallier {
  String name;      // für jedes Objekt separat
  int nummer;       // für jedes Objekt separat
  static int i = 0; // für die gesamte Klasse nur 1-mal!
  public Gallier(String name) {
    this.name = name;
    nummer = i++;
  }
  public void print() {
    System.out.printf("Gallier: %s mit der Nummer %d\n",
                                name, nummer);
  }
  public static void main(String[] args) {
    Gallier c = new Gallier("idefix");
    Gallier d = new Gallier("asterix");
    c.print(); d.print();
    new Gallier("obelix").print(); // (*)‫‏‬
        // Hier "leben" nur noch c und d
        // Das Objekt (*) kann schon hier entsorgt werden.
    }
}
Prof. Dr. Fritz Jobst
Unterklassen und Vererbung
   Wie erfasst man mit dem Schema der OOP
    spezielle Eigenschaften?
   Wie kann man Code für ein Konto z.B. für Giro-
    Konten wieder verwenden?
   Die Antwort sind die Unterklassen. So ist ein
    Girokonto ein spezielles Konto, aber mit
    zusätzlichen Eigenschaften.
   Die allgemeinen Eigenschaften von Konten
    gelten dann auch für Girokonten.
   Also: Der Code für Konten kann für Girokonten
    benutzt werden!


                      Prof. Dr. Fritz Jobst     39
Vererbung
   Dieses Prinzip der Unterklassen heißt in der Sprache der
    Programmierer Vererbung:
   Unterklassen erben die Eigenschaften von Oberklassen.
   Da eine Unterklasse (= Säugetier) zu einer Oberklasse
    (= Wirbeltier) gehört, gelten alle Eigenschaften der
    Oberklasse, d.h. die Software für die Oberklasse gilt
    natürlich auch für die Unterklasse.
   Ein Löwe ist ein Säugetier
       Ein Säugetier ist ein Wirbeltier
   Ein Löwe kann wie ein Säugetier behandelt werden.
    Sogar die Wirbeltier-Methoden können angewandt
    werden!



                               Prof. Dr. Fritz Jobst     40
Vererbung
   Die Software wird also sozusagen geerbt, sie
    muss nicht neu geschrieben werden.
   Die neuen Eigenschaften müssen natürlich noch
    hinzugefügt werden.
   Neue Methoden zur Verarbeitung können
    hinzugefügt werden.
   Aber: vorhandene Methoden können angepasst
    werden
       Die Fortbewegung eines Vogels und die eines Fisches
        unterscheiden sich in zahlreichen Details.


                         Prof. Dr. Fritz Jobst          41
Prof. Dr. Fritz Jobst
Prof. Dr. Fritz Jobst
Geometrische Objekte
   Darstellung als Aufzählung
       Eine Gerade ist ein geometrisches Objekt.
       Ein Punkt ist ein geometrisches Objekt.
       Ein Kreis ist ein geometrisches Objekt.
       Ein Rechteck ist ein geometrisches Objekt.

Geometrisches Objekt


                                                             Rechteck
           Punkt              Gerade
                    Kreis                           usw...


                            Prof. Dr. Fritz Jobst                       44
Prof. Dr. Fritz Jobst
Vererbung in Java am Beispiel
   Beispiel: Chefs sind auch Personen
       Person als Oberklasse (auch Basisklasse genannt)‫‏‬
       Chef ist dann die Unterklasse (auch abgeleitete Klasse genant)‫‏‬
       Chef ist eine Spezialisierung von Person
   class Chef extends Person {
       Zusätzlich zu Personen die Chef-Attribute
       Zusätzlich zu Personen die Chef-Methoden
       Gleiche Methoden wie bei Personen können bei Chefs ein
        anderes Verhalten zeigen!
       Konstruktoren für Chefs
   }
   Bezug zur Oberklasse mit super
       Aus der Sicht von Chef: Person ist die Oberklasse (Basisklasse)‫‏‬



                              Prof. Dr. Fritz Jobst                  46
Beispiel: Chefs sind auch Personen
   Eine Personalverwaltung verwaltet Objekte der Klasse
    Person.
   Sie kann auch Objekte der Klasse Chef verwalten, denn
    ein Chef ist auch eine Person.
   Deswegen braucht die Verwaltung nicht für Chefs neu
    geschrieben werden.
   Dies ist ein großer Vorteil der Objektorientierung:
       Einmal eine Verwaltung schreiben, z.B. für Applets
       Dann läuft diese Verwaltung für alle Applets, z.B.:
       public class MyApplet extends Applet …
       MyApplet ist ein Applet!
   Die Klasse Person wurde bereits vorgestellt, fehlt nur
    noch die Chef-Klasse.
   Beispiel: k03/src/vglpersonen/Person.java

                              Prof. Dr. Fritz Jobst           47
    Die Klasse Chef

public class Chef extends Person {
  private String Abteilung; // Zusaetzliches Attribut
  public Chef (String Name, int PersonalNummer,
               double Gehalt, String Abteilung) {
    super (Name, PersonalNummer, Gehalt); // Konstruktor
    this.Abteilung = Abteilung;            // Attribut
  }

    // Methoden
    public void drucke () {
      super.drucke ();   // Darstellung der Oberklasse rufen
      System.out.println (" Leitung Abteilung " + Abteilung);
    }
}

Beispiel: k03/src/vglpersonen/Chef.java


                           Prof. Dr. Fritz Jobst          48
Die Klasse Personalverwaltung
  public class PersonalVerwaltung {
    public static void main (String args[]) {
          // Die Personalabteilung verwaltet das Personal
          Person personal [] = {
            new Person ("Hitchcock", 0, 1000),
            new Person ("Bond",      7, 2000),
            new Person ("Ford",     99, 3000),
            new Chef   ("Nealy",    1, 9000, "Sun")‫‏‬           Ein Chef
          };
          for (Person p: personal)‫‏‬
            p.drucke ();
          for (Person p: personal)‫‏‬
            p. erhöheGehalt (100);
          for (Person p: personal)‫‏‬
            p.drucke ();
      }
  }

Der Chef ist eine Person. Er wird wie eine Person behandelt.
                          Prof. Dr. Fritz Jobst                    49
UML für Person, Chef und Personalverwaltung


Person                                    hat Personen       PersonalVerwaltung
                                         0..*            1

-name :String                                                +main(String[]):void
-personalNummer :int
-gehalt :double
+main(String[]):void
+getName():String
+drucke():void
+erhoeheGehalt(double):void
+getGehalt():double
+getPersonalNummer():int


Chef

-abteilung :String

+drucke():void




                              Prof. Dr. Fritz Jobst                               50
Zur UML

   Pfeil:
       Ableitung einer Klasse
   Viereck:
       Hat Elemente
       Ausführlicher: siehe Vorlesung Software-Engineering




                          Prof. Dr. Fritz Jobst          51
Späte Bindung
   Die drucke-Methode eines Person-Objekts wird
    aufgerufen.
   Das Objekt "weiß", was es ist. Dies sorgt dafür, dass die
    passende Methode aufgerufen wird.
   Für ein Chef-Objekt ist dies die drucke()-Methode der
    Chef-Klasse, nicht die entsprechende Methode der
    Basisklasse, denn diese wurde überschrieben.
   Diese Bindung einer Methode an ein Objekt zum spätest
    möglichen Zeitpunkt (Ablauf) wird auch als späte
    Bindung bezeichnet.
   Mit dieser Technik der "artgerechten" Behandlung kann
    man Verwaltungssysteme erstellen, die Objekte von
    Klassen verwalten, die es bei der Entwicklung der
    Verwaltung noch nicht gab.

                         Prof. Dr. Fritz Jobst            52
Prof. Dr. Fritz Jobst
Was ist Vererbung? Erweiterbare Records (N.Wirth)‫‏‬

   Ein Chef-Objekt hat zusätzlich zu einem Person-Objekt
    noch eine Abteilung.
   Bei der Konstruktion eines Objekts sind erst die bisher
    vorhandene Teile, danach die Erweiterungen anzugeben.
   Denn die neuen Teile könnten die alten Teile benutzen
   Für Chefs heißt das:
       Zunächst wird der Person-Bestandteil konstruiert.
       Dies ist der Aufruf des Konstruktors der Person-Klasse
       Dann werden die neuen Attribute initialisiert.
   Der Chef ist dann automatisch eine Person
       Er hat alle Eigenschaften einer Person
       Er kann als solche betrachtet werden.
       Er bleibt aber dennoch Chef.


                              Prof. Dr. Fritz Jobst              54
Prof. Dr. Fritz Jobst
Prof. Dr. Fritz Jobst
Reihenfolge der Initialisierung
   In welcher Reihenfolge werden abgeleitete
    Klassen initialisiert?
   Von innen nach aussen / vom Kleinen zum
    Grossen / von der Basisklasse zur abgeleiteten
    Klasse!
   Beispiel:
    class Class2 extends Class1 {
       public Class2(String text) {
         super(text);
         System.out.println("Class2 "
                                     + text);
       }
   Beispiel: k03/src/ClassInitTest.java

                      Prof. Dr. Fritz Jobst      57
Prof. Dr. Fritz Jobst
Kann eine Person Chef sein?
   Gegeben ist
        public     class Chef extends Person …
        Chef c     = new Chef (…);      // klar
        Person     pc = new Chef (…);   // Chefs sind Person
        Person     pp = new Person (…); // klar
   Dann kann man untersuchen:
        Person p = c;
             c ist Chef, also erst recht Person
        Chef c2 = pc; // falsch: Syntaxfehler
             pc ist Chef, aber nicht als solcher für den Compiler erkennbar.
             Hier muss der Cast benutzt werden:
             Chef c2 = (Chef)pc; // Chef bleibt Chef
        Chef c3 = pp; // falsch: Syntaxfehler + falsche Logik
             pp ist kein Chef. Der Versuch, die Person am Compiler „vorbeizumogeln“ und
              als Chef auszugeben, scheitert zur Laufzeit:
             Chef c3 = (Chef)pp;  falsch, Laufzeitfehler



                                      Prof. Dr. Fritz Jobst                        59
Implementierung der späten Bindung
   Das Java-Laufzeitsystem muss dafür sorgen, dass die zur
    Klasse des Objekts passende Methode aufgerufen wird.
   Dazu gibt es verschiedene Ansätze:
       Eine große Tabelle für alle Klassen und Methoden
            Wenn eine Methode aktiviert werden soll, dann wird in einer Tabelle
             mit allen Einträgen von Methoden, Klassen und Parametern die
             passende Methode gesucht.
            Dieses Verfahren ist sehr aufwendig:
            Suche für ein Objekt der Klasse Chef die Methode drucke…
       vTable (virtuelle Methoden Tabelle)‫‏‬
            Für jede Klasse gibt es eine Tabelle mit den Methoden dieser
             Klasse. Diese Tabelle wird aus den Methoden der Basisklasse
             aufgebaut.
            Vorhandene Einträge werden „überschrieben“.
            Neue Einträge können hinzugenommen werden.
            Rufe die Methode mit der Nr. 2 in der vTable auf




                                 Prof. Dr. Fritz Jobst                      60
Prof. Dr. Fritz Jobst
Programmausnahmen
   Basisklasse für Programmausnahmen kann die Klasse
    Exception sein.
   Dann kann man eigene Klassen definieren.
   Sie erben die Funktionalität einer Ausnahme von der
    Klasse Exception:
       Jede Ausnahme ist Exception!
   Beim Auffangen wird zunächst die speziellste, und zum
    Schluss die allgemeinste Klasse aufgefangen.
       Das ist logisch. so kann man Spezialfälle gezielt behandeln.
   Das Beispiel zeigt
       Exception2 extends Exception1 extends Exception




                              Prof. Dr. Fritz Jobst                    62
Programmausnahmen

// Reihenfolge und Behandlung
// von Programmausnahmen
// super: die Oberklasse einer Klasse

class Exception1 extends Exception {
  Exception1 (String text) {super (text);}
}

class Exception2 extends Exception1 {
  Exception2 (String text) {super (text);}
}


                 Prof. Dr. Fritz Jobst   63
Auslösen der Ausnahmen

public class ExceptionDemo {
  void demo (int i) throws
      Exception1, Exception2, Exception {
    if (i == 1)‫‏‬
      throw new Exception1 ("Zusatz 1");
    else if (i == 2)‫‏‬
      throw new Exception2 ("Zusatz 2");
    else if (i == 3)‫‏‬
      throw new Exception ("Zusatz 3");
  }


                 Prof. Dr. Fritz Jobst      64
     Auffangen der Ausnahmen

    public static void main (String[] args) throws Exception {
      ExceptionDemo e = new ExceptionDemo ();
      for (int i = 1; i <= 4; i++)‫‏‬
        try {
          e.demo (i);
        } catch (Exception2 ex) {
          System.out.println (ex);
        } catch (Exception1 ex) {
          System.out.println (ex);
        } catch (Exception ex) {
          System.out.println (ex);
        } finally {
          System.out.println ("Abschlussbehandlung " + i);
        }
    }
}
        Beispiel: k03/src/ExceptionDemo.java

                             Prof. Dr. Fritz Jobst          65
Schnittstellen definieren: interface
   Ein interface enthält Typen und Namen von Methoden
   In keinem Fall eine Implementierung!
   Bespiel:
    public interface Runnable {
      void run ();
    }
   Eine Schnittstelle legt nur die Anforderungen an ein
    Objekt fest.
   Von einem konkreten Objekt darf dann erwartet werden,
    dass es alle im interface genannten Anforderungen
    erfüllt.




                        Prof. Dr. Fritz Jobst         66
Anwendung für Interfaces
   Wenn eine Klasse ein interface implementiert,
    dann verhält sie sich wie dieses.
   Deswegen werden viele Verwaltungssysteme für
    Objekte für interfaces geschrieben:
       Alle Klassen, die dieses interface bieten, können mit
        so einem System verwaltet werden.
   Dieser „Trick“ ist grundlegend für die Architektur
    vieler Java-Systeme.




                          Prof. Dr. Fritz Jobst           67
Schnittstellen implementieren: implements
   Wenn eine Klasse eine Schnittstelle implementiert, dann
    können Objekte dieser Klasse gemäß dieser Schnittstelle
    benutzt werden, d.h. man kann für solche Objekte die
    entsprechenden Methoden aufrufen.
   Dabei müssen ohne Ausnahme alle im interface
    angegebenen Methoden überschrieben werden.
public class MeineKlasse implements Runnable {
  public void run () {
    … Implementierung
  }
}
   Beispiele: k03/src/CloneableDemo.java,
    k03/src/vglpersonen/*

                         Prof. Dr. Fritz Jobst          68
Beispiel: Geometrische Objekte
//   Geometrische Objekte eignen sich gut als Einstieg
//   in die objektorientierte Denkweise.
//   Erweitern Sie die hier vorliegenden Objekte
//   beliebig!
import   java.applet.Applet;
import   java.awt.Graphics;
import   java.awt.event.MouseAdapter;
import   java.awt.event.MouseEvent;
// Die Schnittstelle ist der Vertrag zwischen
// Implementierung und Anwendung
interface GeometrieObjekt {
  public void paint (Graphics g);
  public boolean contains (int x, int y);
  public String getName ();
}

                       Prof. Dr. Fritz Jobst        69
Ein Kreis
 // Der Kreis muss alle Methoden der Schnittstelle
 // implementieren.
 // Er verhält sich wie ein geometrisches Objekt!
 class Kreis implements GeometrieObjekt {
   private int r;      // r = Radius
   private int mx, my; // mx, my = Mittelpunkt
   public Kreis (int r, int x, int y) {
     this.r = r; mx = x; my = y;
   }
   public void paint (Graphics g) {
     g.drawArc (mx-r, my-r, 2*r, 2*r, 0, 360);
   }
   public boolean contains (int x, int y) {
     return (mx-x)*(mx-x)+(my-y)*(my-y) <= r*r;
   }
   public String getName () { return "Kreis"; }
 }
                       Prof. Dr. Fritz Jobst         70
Ein Rechteck
// Das Rechteck muss alle Methoden der Schnittstelle
  implementieren.
// Es verhält sich wie ein geometrisches Objekt!
class RechtEck implements GeometrieObjekt {
  private int x, y, b, h; // Linke obere Ecke, Breite, Höhe
  public RechtEck (int x, int y, int b, int h) {
    this.x = x; this.y = y;
    this.b = b; this.h = h;
  }
  public void paint (Graphics g) {
    g.drawRect (x, y, b, h);
  }
  public boolean contains (int x, int y) {
     return this.x <= x && x <= this.x+b &&
            this.y <= y && y <= this.y+h;
  }
  public String getName () { return "Rechteck"; }
}

                       Prof. Dr. Fritz Jobst           71
    Die Verwaltung
public class GeometrischeObjekteInterface extends Applet {
  private GeometrieObjekt geo [] = new GeometrieObjekt[5];
  public void init () {
    geo[0] = new Kreis (30, 50, 70);
    for (int i = 1; i < geo.length; i++)‫‏‬
      geo[i] = new Rechteck (20+i*10, 10+i*10, 100, 15);

        addMouseListener (new MouseAdapter() {
          public void mouseClicked (MouseEvent event) {
            int x = event.getX(); // Nur als Anfangspunkt notieren
            int y = event.getY();
            String Treffer = "click: x = " + x + " y = " + y;
            for (GeometrieObjekt go : geo)‫‏‬
              if (go.contains (x, y))‫‏‬
                Treffer = Treffer + " " + go.getName ();
            showStatus (Treffer);
          }
        });
    }

    public void paint (Graphics g) {
      for (GeometrieObjekt go : geo)‫‏‬
        go.paint (g);
    }
}




                                         Prof. Dr. Fritz Jobst       72
    UML


                <<interface>>                                               GeometrischeObjekteInterface
                                                 hat Geometrische Objekte
                GeometrieObjekt
                                                     0..*            1
                                                                            -geo :GeometrieObjekt[]
                +getName():String
                +contains(int,int):boolean                                  +init():void
                +paint(Graphics):void                                       +paint(Graphics):void


Kreis                             Rechteck

-r :int                           -x   :int
-mx :int                          -y   :int
-my :int                          -b   :int
                                  -h   :int
+getName():String
+contains(int,int):boolean        +getName():String
+paint(Graphics):void             +contains(int,int):boolean
                                  +paint(Graphics):void



        Beispiel:
        k03/src/GeometrischeObjekteInterface.java

                                        Prof. Dr. Fritz Jobst                                         73
Zusammenfassung
   Die Verwaltung hängt nicht von den konkreten
    geometrischen Objekten ab!
   Die Verwaltung muss nicht bei jedem neuen Typ
    von Objekt neu geschrieben werden.
   So kann man Dienste für Klassen anbieten, die
    nur bestimmte Methoden implementieren
    müssen. Und schon kommen sie in den Genuss
    der Dienste.




                     Prof. Dr. Fritz Jobst    74
class und interface, extends und implements
   class                                    interface
   enthält Daten+Methoden                   enthält nur* Methodenköpfe
   x extends basis                          x implements basis
   x erbt Code+Daten von basis              x muss alle Methoden von basis
   Mehrfachvererbung NICHT                   implementieren
    möglich. Man kann nur von                x muss die von basis gefor-
    einer Klasse erben.                       derte Schnittstelle
                                              implementieren
                                             Implementieren mehrerer
                                              Schnittstellen möglich

Fazit: zwar sind extends und implements zwei Formen
der Vererbung, aber:
•bei extends kann etwas geerbt werden,
•bei implements erbt man nur Vorschriften, sich
gemäß der Schnittstelle zu verhalten
                            Prof. Dr. Fritz Jobst                       75
Generische Klassen in Java 5
   Eine einfache generische Operation ist die Addition a+b.
   Sie ist in einheitlicher Form geschrieben, egal, ob die
    Operanden vom Typ int, float oder double sind.
   Auch das Verfahren zur Bestimmung des Maximums
    zweier Zahlen ist unabhängig vom Typ.
   Deswegen versucht man in diversen
    Programmiersprachen, Code für solche generischen
    Operationen nur einmal zu schreiben.
       Man parametrisiert den Typ, entwickelt einmal und nur einmal
        den Code und benutzt ihn mit Daten der verschiedenen Typen.
   Java unterstützt ab JDK 1.5 generische Typen für alle
    Referenztypen, d.h. für Klassen, Interfaces und Arrays,
    nicht jedoch für die Basisdatentypen wie int, float …


                             Prof. Dr. Fritz Jobst                76
Eine Klasse für ein Paar von Objekten

   Diese Unterstützung ist insbesondere dann
    nützlich, wenn man Objekte aufbewahrt.
   Das folgende Beispiel zeigt die Klasse Pair für
    beliebige Referenztypen.
// Generische Paar-Klasse : Definition 1
    class Pair<E> {
       public Pair (E first, E second) {
         this.first= first;
         this.second = second;
       }
       public E first;
       public E second;
     }


                         Prof. Dr. Fritz Jobst        77
Verschiedene Paare von Objekten
// Ein neues Paar von Personen:
Pair <Person> p = new Pair<Person> (
    new Person ("a", 1, 1000.0),
    new Person ("b", 2, 2000.0));
Person xx = a.first;

// Ein Chef ist eine Person, also ist auch dies
// ein Paar von Personen:
Pair <Person> q = new Pair<Person> (
    new Person ("c", 3, 1000.0),
    new Chef   ("d", 4, 2000.0, "a1"));

// Natürlich gibt es auch ein Paar von Chefs:
Pair <Chef>    c = new Pair<Chef> (
    new Chef   ("e", 5, 1000.0, "a2"),
    new Chef   ("f", 6, 2000.0, "a3"));


Beispiel: k03/src/MyGenericsDemo.java

                          Prof. Dr. Fritz Jobst   78
Ein Chef ist eine Person.
Ist ein Paar von Chefs auch ein Paar von Personen?

   Die emotionale Antwort auf diese Frage ist ein klares Ja.
   Die Antwort des Compilers auf diese Frage ist ein klares Nein, er
    übersetzt eine Wertzuweisung der folgenden Art nicht.
   Pair<Person> p = new Pair<Chef> (…, …); // Fehlerhaft !!!!
   Zur Erklärung dieses Phänomens muss man sich die Folgen
    überlegen, die eintreten könnten, wenn ein Compiler die obige
    Anweisung übersetzen würde.
   Pair<Person> p = c; // Ein Paar von Chefs = ein Paar Personen
   p.first = new Person (…);
   Da p.first = c.first wäre im Paar c von Chefs das erste Element eine
    Person, das zweite Element ein Chef.
   Damit wäre das Konzept der Typsicherheit ausgehebelt, denn der
    „Behälter“ hatte zugesichert, dass er nur Chefs aufnimmt, und eine
    Person ist eben nicht à priori ein Chef




                              Prof. Dr. Fritz Jobst                  79
Autoboxing und Unboxing

   In Java gibt es die elementaren Datentypen wie
    int, float, char und die Referenztypen.
   Die Referenztypen profitieren von den Vorteilen
    der Objektorientierung.
   Die elementaren Datentypen werden in
    Programmen mit intensiver Verarbeitung
    benötigt, um die Laufzeit knapp zu halten.
   Der Übergang von einem Typsystem zum
    anderen sieht wie folgt aus:
    Integer i1 = new Integer (20);
    int i      = i1. intValue();


                        Prof. Dr. Fritz Jobst    80
Autoboxing und Unboxing
   Der Übergang von einem Typsystem zum anderen sieht
    wie folgt aus:
    Integer i1 = new Integer (20);
    int i         = i1. intValue();

                           Boxing


             20                                        20



                           Unboxing


    Integer i1 = 20;
    int i         = i1;

   Vergleichen Sie dies mit Ein-/Auspacken.
   Beispiel: k03/src/Autoboxing.java

                               Prof. Dr. Fritz Jobst        81
Variable Anzahl von Argumenten
   In manchen Methoden kennt man die Anzahl der übergebenen Parameter
    nicht.
   Natürlich kann man die Parameter in einem Feld aus Objekten
    zusammenfassen und dieses Feld als Parameter übergeben, jedoch ist die
    Formulierung für die printf-Methode im JDK 1.5 ebenso elegant wie bequem
    in der Anwendung.
// Definition …
public PrintStream printf (String format, Object... arguments);
// Aufruf …
int a, b, c; … //Werte zuweisen
   System.out.printf ("Die Summe aus %d und %d ist %d\n", a, b, c);
   Die Schreibweise für printf könnte ohne Autoboxing nicht so einfach sein,
    denn dann müsste etwa a in der Form new Integer (a) übergeben werden.
   Wenn man eigene Methoden mit einer variablen Anzahl von Argumenten
    schreiben möchte, muss man darauf achten, dass die Aufrufe klar von ggfs.
    vorhandenen überladenen Aufrufen unterschieden sind.




                               Prof. Dr. Fritz Jobst                     82
    Aufzählung von Konstanten: enum
    In Java kann man Konstanten in der folgenden Form definieren.
    public static final int ROT    = 0;
    public static final int GRUEN = 1;
    public static final int GELB   = 2;
    public static final int MONTAG = 1;
    int farbe = ROT;   // Zuweisung ist sinnvoll
    farbe = MONTAG;    // ??? Missverständnis
                          // Für den Compiler ist das kein Problem!
    Die grau hinterlegte zweite Wertzuweisung in obigem
     Programmabschnitt illustriert das Problem:
       Konstanten dieser Art sind nicht typgebunden.
       Durch dieses Loch im Sicherheitsnetz der Typüberprüfung können Fehler
        schlüpfen, die erst zur Laufzeit des Programms sichtbar werden.
    Eine Testhilfe kann mit reinen int-Daten auch nicht auf die vom
     Programmierer gedachte Bedeutung einer Konstante schließen.
       Was sollte die Testhilfe bei farbe ausgeben?
    Beispiel: k03/src/FinalDemo.java


                                  Prof. Dr. Fritz Jobst                  83
Java 5 bietet enum-Klassen
   Die enum-Typen können in switch-Anweisungen zur
    Definition von case-Alternativen benutzt werden.
     enum Farben {
          ROT, GRUEN, GELB
       };

    enum Tage {
       MONTAG, DIENSTAG, MITTWOCH,
       DONNERSTAG, FREITAG,
       SAMSTAG, SONNTAG
    };


                       Prof. Dr. Fritz Jobst       84
Einfache Anwendung von enum

   … in einer Methode:
    Farben farbe = Farben.ROT;           // In Ordnung
    farbe        = Tag.MONTAG;           // So nicht: Fehler
   … Anwendung bei switch
    switch (farbe) {
      case ROT:
        …
        break;
      case GRUEN:
        …
        break;
    }
   Beispiele:
       k03/src/MyEnumTest.java
       k03/src/DemoFuerEnum.java
                          Prof. Dr. Fritz Jobst                85
Dynamische Erzeugung von Objekten
   Java erlaubt die Erzeugung von Objekten, wenn nur der Name der Klasse
    bekannt und ein parameterloser Konstruktor vorhanden ist.
   Diesen Namen kann man in Form einer Zeichenkette als Parameter oder
    über einen Eingabe-dialog an das Programm übergeben.
   Damit lässt sich in Java-Programme noch zur Laufzeit bis zum spätest
    möglichen Moment, nämlich gerade vor der Ausführung, eine bis dahin
    völlig unbekannte Klasse integrieren.
   Diese Technik der Erzeugung von Objekten kann man zusammen mit
    abstrakten Basisklassen oder auch mit Interfaces benutzen.
   Man spezifiziert in der Superklasse die Schnittstelle, etwa die allgemeinen
    Dienste der Klasse.
   Die tatsächliche Klasse wird dann zum spätest möglichen Zeitpunkt
    aufgrund einer Eingabe des Anwenders geladen.
   Das Entscheidende an diesem Verfahren ist die Tatsache, dass man zum
    Zeitpunkt der Entwicklung der Rahmen-steuerung nicht einmal den
    Namen der zum Einsatz kommenden Klasse kennen muss.
   Es ist lediglich die Funktionalität zur Integration in das Programm über die
    abstrakte Superklasse zu spezifizieren.




                               Prof. Dr. Fritz Jobst                       86
Schreibweise in Java
 // Anfordern von Exemplaren von Klassen
 // NUR ÜBER DEN NAMEN DER KLASSE!!
 public Object ClassStart (String name) {
   Class newObject = null;
   try {
     newObject = Class.forName(name);
     return newObject.newInstance ();
   } catch (Exception e) {
     e.printStackTrace (System.err);
     return null;
   }
 }




                      Prof. Dr. Fritz Jobst   87
Zusicherungen

   Mit dem JDK 1.4 wurden Zusicherungen in Java
    eingeführt.
   Eine Zusicherung (Assertion) ist ein mit dem
    neuen Schlüsselwort assert eingeleiteter
    Boolescher Ausdruck, den der Programmierer
    als wahr erwartet, wenn die weitere Arbeit des
    Programms sinnvoll sein soll.
   Z.B. könnte eine Methode zum Aufsummieren
    von Komponenten eines Feldes voraussetzen,
    dass die Referenz auf das Feld nicht null ist.


                    Prof. Dr. Fritz Jobst      88
Beispiel für eine Zusicherung (Assertion)‫‏‬
public class ZusicherungsDemo {
  public static int summiere (int[] feld) {
    assert feld != null;
    int summe = 0;
    for (int i: feld)‫‏‬
      summe += i;
    return summe;
  }
  public static void main (String[] args) {
    int[] f1 = {1, 2, 3};
    int[] f2 = null;
    System.out.println (summiere (f1));
    System.out.println (summiere (f2));

    }
}

Beispiel: k03/src/ZusicherungsDemo.java

                        Prof. Dr. Fritz Jobst   89
Zusammenfassung
   Wege zu Klassen und Objekten
   Attribute, Methoden und Konstruktoren
   this
   String und StringBuffer
   static oder nicht static?
   Unterklassen, Vererbung und späte Bindung
   cast für Objekte
   Klassen und Ausnahmen
   Interface
   Generische Klassen
   enum
   Dynamische Erzeugung von Objekten
   Autoboxing, Unboxing
   Parameter in variabler Anzahl


                            Prof. Dr. Fritz Jobst   90
Literatur
   Dr. Uwe Aßmann, Uni Karlsruhe, Vorlesung 2001
       info2-07-01-oo-einfuehrung.ppt
   Fritz Jobst, Programmieren in Java, 5. Auflage
    Oktober 2005, Carl Hanser Verlag
   Joshua Bloch, Effective Java, Addison Wesley,
    10th printing, Juli 2005
   The Java Language Specification, 3rd Ed, James
    Gosling, Bill Joy, Guy Steele, Gilad Bracha,
    Addison Wesley, 2005
   Generics in the Java Language, Gilad Bracha,
    Juli 2004,
    http://java.sun.com/j2se/1.5/pdf/generics-
    tutorial.pdf

                         Prof. Dr. Fritz Jobst   91

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:6
posted:2/21/2012
language:
pages:91