Info B VL 4: Konstruktoren und Vererbung · 2007. 10. 9. · Vererbung Objektorientiere...

30
Info B VL 4: Konstruktoren und Vererbung Objektorientiere Programmierung in Java 2003 Ute Schmid (Vorlesung) Elmar Ludwig ( ¨ Ubung) FB Mathematik/Informatik, Universit ¨ at Osnabr ¨ uck Info B VL 4: Konstruktoren und Vererbung – p.83

Transcript of Info B VL 4: Konstruktoren und Vererbung · 2007. 10. 9. · Vererbung Objektorientiere...

  • Info B VL 4: Konstruktoren undVererbung

    Objektorientiere Programmierung in Java2003

    Ute Schmid (Vorlesung)

    Elmar Ludwig (Übung)

    FB Mathematik/Informatik, Universität Osnabrück

    Info B VL 4: Konstruktoren und Vererbung – p.83

  • Konstruktoren

    Spezielle Funktion zur Erzeugung von Objekten

    Ursprünglich: in funktionaler Programmierung undTyptheorie als Symbol zur Erzeugung einesalgebraischen Datentyps

    Beispiel in ML:

    datatype ’a list = nil | :: of ’a * ’a list

    Ausdrücke, die nur Konstruktoren enthalten sind inNormalform (werden nicht weiterausgewertet/reduziert)

    Funktionen über algebraischen DTs können patternmatching verwenden:

    fun f(nil) = nil

    | f(x::l) = if even(x) then f(l) else x::f(l);

    Info B VL 4: Konstruktoren und Vererbung – p.84

  • Konstruktoren in OO-Sprachen

    mit C++ eingeführt

    Konstruktor wird von einer Klasse zur Verfügunggestellt und dient der Initialisierung eines Objekts

    � � da neue Objekte meist über Konstruktoraufruferzeugt werden kann Initialisierung nicht vergessenwerden

    In C++ und Java: Konstruktornamen gleichKlassennamen

    In C++: Destrukturen als Gegenstück (Freigabe vonRessourcen)In Java kaum notwendig wegen Garbage Collector

    Info B VL 4: Konstruktoren und Vererbung – p.85

  • Konstruktor-Definition

    Konstruktoren haben keinen Rückgabetyp (auch nichtvoid)

    Wird für eine Klasse kein Konstruktor definiert, so wirdein Default Konstruktor (auch “no-arg constructor”)angelegt

    Der Default Konstruktor hat keine Argumente

    Alle Konstruktoren haben implizit eine Referenz zumneu erzeugten Objekt (this) als Argument

    Im Konstruktor-Körper werden die Initialisierungen desthis-Objekts vorgenommen.

    Beispiel: Initialisierung eines Circle-Objektspublic Circle(double r) { this.r = r; }

    ...

    Circle c = new Circle(2.0);Info B VL 4: Konstruktoren und Vererbung – p.86

  • Definition mehrerer KonstruktorenMöglichkeit, Objekt auf verschiedene Art zuinitialisierenpublic Circle() { r = 1.0; }

    public Circle(double r) { this.r = r; }

    Wie bei Methoden gilt overloading: gleicher Name aberunterschiedliche Signaturen (Anzahl und Typ derArgumente)

    Ein Konstruktor kann andere Konstruktoren aufrufen:this() als Konstruktoraufruf; welcher Konstruktoraktiviert wird, hängt wieder von Anzahl und Typ derArgumente ab.

    Verwendung von this() ist gute Strategie, wenn dieKonstruktoren Teile der Initialisierung gemeinsamhaben

    this() darf nur als erste Anweisung in einemKonstruktor vorkommen Info B VL 4: Konstruktoren und Vererbung – p.87

  • Beispiel ‘Circle’

    // This is the basic constructor:

    // initialize the radius

    public Circle(double r) { this.r = r; }

    // This constructor uses this() to invoke

    // the constructor above

    public Circle() { this(1.0); }

    Info B VL 4: Konstruktoren und Vererbung – p.88

  • Default Werte

    Lokale Variablen (innerhalb von Methoden definiert)haben keine Default-Werte

    Werden lokale Variablen nicht vor ihrer Verwendunginitialisiert, liefert der Java-Compiler eineFehlermeldlung!

    (Klassen- und Instanz-) Felder sind automatisch mitDefault-Werten initialisiert

    Übliche Deklaration mit Zuweisung eines initialenWertes ist ebenfalls möglich

    public static final double PI = 3.14159;

    public double r = 1.0;

    Info B VL 4: Konstruktoren und Vererbung – p.89

  • Default Werte für Felder

    Typ Defaultboolean false

    char ‘

    u0000’

    byte, short, int, long 0float, double 0.0reference null

    Info B VL 4: Konstruktoren und Vererbung – p.90

  • Initialisierung von Instanz-FeldernKonstruktoren

    Java Compiler erzeugt Initialisierungscode fürInstanz-Felder und fügt sie in Konstruktor(en) ein

    Reihenfolge: die im Programm angegebene (Nutzungvon bereits initialisierten Feldern bei der Initialisierungweiterer Felder möglich)

    Wenn ein Konstruktor mit this() Anweisung beginnt,dann wird in diesen Konstruktor die Initialisierung nichteingefügt, sondern in denjenigen Konstruktor, derdurch this() aktiviert wird

    ab Java 1.1: Initialisierungsblöcke für Instanz-Felder:

    ...

    , die an beliebiger Stelle (an der

    Komponenten stehen können) in die Klasse eingefügtwerden können; üblich: direkt nach Feld; benutzt vorallem für anonyme innere Klassen

    Info B VL 4: Konstruktoren und Vererbung – p.91

  • Beispielpublic class TestClass {

    public int len = 10;

    public int[] table = new int[len];

    public TestClass(){

    for (int i = 0; i < len; i++) table[i] = i;

    } }

    Ist äquivalent zupublic class TestClass {

    public int len;

    public int[] table;

    public TestClass() {

    len = 10;

    table = new int[len];

    for (int i = 0; i < len; i++) table[i] = i;

    } } Info B VL 4: Konstruktoren und Vererbung – p.92

  • Initialisierung von Klassen-Feldern (1)

    Statische Initialisierungs-Blöcke

    Klassen-Felder existieren auch wenn kein Objekterzeugt wird

    Initialisierung vor Konstruktoraufruf notwendig

    � � Java Compiler erzeugtKlassen-Initialisierungs-Methode (interne, versteckteMethode �clinit � ), in der alle Klassen-Felderinitialisiert werden.Diese Methode wird genau einmal ausgewertet,nämlich wenn die Klasse das erstemal benutzt(geladen) wird.

    Initialisierung wieder in der im Programmangegebenen Reihenfolge

    Info B VL 4: Konstruktoren und Vererbung – p.93

  • Init. von Klassen-Feldern (2)

    Explizite Initialisierung von Klassen-Feldern mit staticinitializer Block: static

    ...

    , der an jeder

    Stelle der Klasse stehen kann, wo Komponentenstehen können

    Es kann mehrere solche Initialisierungs-Blöcke geben

    Initialisierungs-Blöcke werden vom Compiler in dieKlassen-Initialisierungs-Methode integriert

    Statische Initialisierung ist wie eine Klassen-Methode,also keine Verwendung von this möglich, keineNutzung von Instanz-Komponenten möglich

    Info B VL 4: Konstruktoren und Vererbung – p.94

  • Beispiel

    // We can draw the outline of a circle using trigonometric functions

    // Trigonometry is slow, though, so we precompute a bunch of values

    public class TrigCircle {

    // Here are our static lookup tables and their own simple initializers

    private static final int NUMPTS = 500;

    private static double sines[] = new double[NUMPTS];

    private static double cosines[] = new double[NUMPTS];

    // Here’s a static initializer that fills in the arrays

    static {

    double x = 0.0;

    double delta_x = (Circle.PI/2)/(NUMPTS-1);

    for (int i = 0; i < NUMPTS; i++, x += delta_x) {

    sines[i] = Math.sin(x);

    cosines[i] = Math.cos(x);

    } } }

    Info B VL 4: Konstruktoren und Vererbung – p.95

  • Garbage Collection (1)

    Mit new werden neue Objekte erzeugt (heap)

    Wenn ein Objekt nicht länger benutzt wird, wird derSpeicherplatz automatisch freigegeben (garbagecollection)

    Der Java Interpreter weiss, welche Objekte und Arrayser angelegt (allocated) hat, und kann ermitteln, welcheObjekte und lokale Variablen auf andere Objekteverweisen.

    Wenn kein Verweis auf ein Objekt existiert, kann eszerstört werden; dito für nicht mehr referenzierteVerweis-Zyklen

    Info B VL 4: Konstruktoren und Vererbung – p.96

  • Garbage Collection (2)

    Garbage Collector läuft immer im Hintergrund als lowpriority thread; wird im Normalfall immer aktiv, wennnichts Wichtiges passiert (z.B. beim Warten auf Input),ausser: wenn kaum noch freier Speicher vorhanden ist

    Garbage Collection kann nie so effizient sein wie guteselbstgeschriebene Speicherverwaltung (free(),delete); aber es verhindert Fehler (z.B. memoryleaks) und erlaubt schnellere Entwicklung von Code.

    Info B VL 4: Konstruktoren und Vererbung – p.97

  • Finalization

    Freigabe von bestimmten Resourcen, die ein Objektbenutzt, wird nicht vom Garbage Collector erledigt(z.B. temporäre Dateien löschen)

    Finalizer ist Instanz-Methode, Gegenstück zuKonstruktor (“Destruktor”); wird vom Garbage Collectoraufgerufen; keine Argumente, kein Rückgabewert

    Es darf nur einen Finalizer pro Klasse geben.

    protected void finalize()

    Selbstgeschriebene Klassen benötigen selten expliziteFinalizer (Ausnahme native finalize fürSchnittstellen zu Code, der nicht unter Kontrolle desGarbage Collectors ist)

    Info B VL 4: Konstruktoren und Vererbung – p.98

  • Exkurs: Semantische Netze

    Birdhas wingscan flyhas feathers

    Fishhas finscan swimhas gills

    Animal

    has skincan move aroundeatsbreathes

    Ostrichhas thin long legsis tallCanary

    is yellow

    can singShark

    can bite

    is dangerousSalmon

    is pinkis edible

    swims upriverto lay eggs

    can’t fly

    Info B VL 4: Konstruktoren und Vererbung – p.99

  • Kognitive Ökonomie

    Objekte sind hierarchisch organisiert

    Eigenschaften werden nur einmal gespeichert undvererbt

    Psychologische Experimente: Antwortzeiten (Collins &Quillian)

    Prolog: flache, logische Repräsentation, Vererbung viaexpliziert Transitivitätsregel

    “natürlicher”: OO-Sprache, Ober-/Unterklassen werdennur je einmal angegeben

    Info B VL 4: Konstruktoren und Vererbung – p.100

  • Prolog

    /* Fakten */

    isa(canary, bird).

    isa(ostrich, bird).

    isa(bird, animal).

    isa(shark, fish).

    isa(salmon, fish).

    isa(fish, animal).

    has(skin, animal).

    does(eat, animal).

    ...

    /* Inferenzregeln */

    is_a(A,B) :- isa(A,B). /* direkter Fall */

    is_a(A,C) :- isa(A,B), is_a(B,C). /* Transitivitaet */

    /* analog fuer has, does, ... */

    Info B VL 4: Konstruktoren und Vererbung – p.101

  • Java

    class Animal {

    boolean hasSkin = true;

    boolean canEat = true;

    }

    class Bird extends Animal {

    boolean hasWings = true;

    boolean canFly = true; // default,

    // gilt nicht fuer alle Voegel

    }

    class Ostrich extends Bird {

    Ostrich() { canFly = false; }

    }

    Info B VL 4: Konstruktoren und Vererbung – p.102

  • Erweiterung von ‘Circle’

    Beispielcode: PlaneCircle.java

    + isInside

    PlaneCircle

    cycx

    Circle

    PIr

    + radiansToDegrees+ area+ circumference

    Info B VL 4: Konstruktoren und Vererbung – p.103

  • Erweiterung einer Klasse

    Funktionale Erweiterung von Klassen durchUnterklassenbildung ist zentral für objekt-orientierteProgrammierung

    class � Name � extends � SName � { ... }

    Felder und Methoden der Oberklasse werdenautomatisch vererbt, Konstruktoren nicht!

    Unterklassen-Konstruktor kann Konstruktor derOberklasse durch super() aufrufen (analog zuthis())

    Weitere Felder und Methoden können für dieUnterklasse definiert werden.

    Info B VL 4: Konstruktoren und Vererbung – p.104

  • Typkonversion

    Typkonversion zwischen Unter- und Oberklassen:von Unterklasse zu Oberklasse (upcasting), Objektwird allgemeiner (verliert Zugriff auf spezielle Felderund Methoden) ohne Casting;von Oberklasse zu Unterklasse (downcasting): Castingnotwendig (und Prüfung zur Laufzeit durch die VM)(vergleiche widening und narrowing bei primitivenDatentypen)

    PlaneCircle pc = new PlaneCircle(2.0, 5.0, 5.0);

    double ratio = pc.circumference() / pc.area();

    Circle c = pc; // no access to positioning

    PlaneCircle pc2 = (PlaneCircle) c;

    boolean oins = ((PlaneCircle) c).isInside(0.0, 0.0);

    Info B VL 4: Konstruktoren und Vererbung – p.105

  • KapslungWichtige objekt-orientierte Technik: Information-Hiding,Encapsulation:

    Daten nur über Methoden zugänglich machenDaten und interne (private) Methoden sind sicher inder Klasse eingeschlossen und können nur vonvertrauenswürdigen Nutzern (also über ordentlichdefinierte öffentliche Methoden der Klasse) benutztwerden.

    Schutz der Klasse gegen absichtliche oderunabsichtliche Eingriffe

    Verstecken interner Implementations-Details. Ändernder Implementation, ohne dass genutzter Code dieserKlasse betroffen ist.

    Übersichtlichkeit durch kleine Menge öffentlicherInformation

    Info B VL 4: Konstruktoren und Vererbung – p.106

  • ZugriffskontrollePaket-Zugriff: Nicht Teil von Java selbst (Lesbarkeitvon Dateien, Verzeichnissen)

    Klassen-Zugriff: Default ist, dass top-level Klassenpaket-weit zugreifbar sind. public deklarierte Klassensind überall (wo das Paket zugreifbar ist) zugreifbar.

    Zugriff auf Komponenten einer Klasse: Komponentensind in jedem Fall in der Klasse selbst zugreifbar;Default: paket-weiter Zugriff;Alle Klassen, die zum selben Paket gehören, dürfenzugreifen. Bei unbenanntem Paket typischerweise alleKlassen im selben Verzeichnis(implementationsabhängig).

    Zugriffsmodifikatoren: public, protected, privatefür Felder und Methoden.

    Info B VL 4: Konstruktoren und Vererbung – p.107

  • Zugriffsmodifikatoren

    Für Klassen-Komponenten:

    public: von überall (wo Paket zugreifbar ist)zugreifbarprotected: paket-weit und aus allen Unterklassen(egal, in welchem Paket sie definiert sind) zugreifbardefault: paket-weit zugreifbar (wenn kein Modifikatorangegeben)private: nur in der Klasse selbst zugreifbar

    Accessible to public protected ‘package’ private

    Defining class yes yes yes yes

    Class in same package yes yes yes no

    Subclass in different package yes yes no no

    Non-subclass in different package yes no no no

    Info B VL 4: Konstruktoren und Vererbung – p.108

  • Zugriff und Vererbung

    Unterklasse erbt alle Instanz-Felder und -Methodender Oberklasse. Manche Komponenten sind aufgrundder Einschränkung der Sichtbarkeit nicht zugreifbar.

    Wenn Ober- und Unterklasse im selben Paket: Zugriffauf alle nicht-privaten Felder und Methoden.

    Wenn Ober- und Unterklasse in verschiedenenPaketen: Zugriff auf alle public und protectedFelder und Methoden.

    private Komponenten und Konstruktoren können nieausserhalb der Klasse zugegriffen werden.

    Subtile Probleme: wie verhält sich protected, wennKlasse A und Unterklasse B in verschiedenen Paketenstehen und Klasse B in Klasse A genutzt wird? Wiespielen Casting und Zugriffsmodifikatoren zusammen?

    Info B VL 4: Konstruktoren und Vererbung – p.109

  • Beispiel

    Circle mit protected r.PlaneCircle (ist Unterklasse) in anderem Paket.Methode in PlaneCircle:public boolean isBigger (Circle c) {

    return (this.r > c.r);

    }

    Compiler-Fehler: Zugriff auf this.r ist erlaubt, da dasFeld r von der Unterklasse PlaneCircle geerbt wird.Aber: Zugriff auf c.r ist in PlaneCircle nicht erlaubt!

    Wäre erlaubt, wenn PlaneCircle c anstelle vonCircle c, oder wenn Circle und PlaneCircle imselben Paket definiert wären

    Info B VL 4: Konstruktoren und Vererbung – p.110

  • DaumenregelnBenutze public nur für Methoden und Konstanten,die den öffentlichen Teil des API der Klasse darstellensollen.Kapsle Felder: als privat deklarieren und Zugriff überpublic Methoden

    Benutze protected für Komponenten, die bei derErzeugung von Unterklassen notwendig sein könnten.Achtung: Änderung von protected Komponentenkann im Code der Klasse Inkonsistenzen erzeugen.

    Benutze default Sichtbarkeit für Komponenten, dieinterne Implementation realisieren und von Klassen imselben Paket genutzt werden sollen.Nutzung der package Anweisung, um miteinanderkooperierende Klassen in ein Paket zu bündeln.

    Sonst benutze private.

    Besser zunächst möglichst restriktive Rechte vergeben und

    erst wenn nötig lockern.

    Info B VL 4: Konstruktoren und Vererbung – p.111

  • Zugrifffsmethoden

    Beispielprogramm: myshapes.Circle

    Klasse ist einem Paket zugeordnet (Verzeichnisnamegleich dem Paketnamen).

    Methoden sind um Fehlerprüfung erweitert (explizitecheckXX() Methoden).

    Zugriff auf Werte von Instanz-Feldern erfolgt überMethoden (setXX(), getXX()).Felder, auf die mit set- und get-Methoden zugegriffenwird, werden auch Properties genannt. Man sprichtvon “Getter”- und “Setter”-Methoden.

    Info B VL 4: Konstruktoren und Vererbung – p.112

    KonstruktorenKonstruktoren in OO-SprachenKonstruktor-DefinitionDefinition mehrerer KonstruktorenBeispiel `Circle'Default WerteDefault Werte für FelderInitialisierung von Instanz-FeldernBeispielInitialisierung von Klassen-Feldern (1)Init. von Klassen-Feldern (2)BeispielGarbage Collection (1)Garbage Collection (2)FinalizationExkurs: Semantische NetzeKognitive ÖkonomiePrologJavaErweiterung von `Circle'Erweiterung einer KlasseTypkonversionKapslungZugriffskontrolleZugriffsmodifikatorenZugriff und VererbungBeispielDaumenregelnZugrifffsmethoden