Programmieren Tutorium 12

Interfaces, Generics, Rekursion

Gliederung

  • Interfaces
  • Generics
  • Rekursion

Interfaces

Was ist das?

  • Definition einer Schnittstelle
    • Reine Definition eines Typen (Menge von Methoden-Signaturen)
  • kann zur Typisierung verwendet werden
    • Eine Klasse C, die ein Interface I implementiert, bildet einen Subtyp von I
  • Vergleichbar mit komplett abstrakter Klasse

Verwendung

// Interface-Deklaration
interface Foo {
    static final int QUUX = 42;
    void foo();
}

// Implementierung
class Bar implements Foo, Baz {
    @Override
    public void foo() { ... }
}

Foo f = new Bar();

Vererbung

interface I {
    void foo();
}

interface J extends I, K {
    void bar();
}
  • Interfaces können voneinander erben
  • Mehrfachvererbung möglich

Übungsaufgabe

WS 12/13, ÜB 5
Aufgabe A.1

Generics

(parametrisierte Typen)

Was ist das?

Die Idee dahinter ist, zusätzliche Variablen für Typen einzuführen. Diese Typ-Variablen repräsentieren zum Zeitpunkt der Implementierung unbekannte Typen. Erst bei der Verwendung der Klassen, Schnittstellen und Methoden werden diese Typ-Variablen durch konkrete Typen ersetzt.

Wofür ist das gut?

Code von Container-Datentypen (und anderen Datenstrukturen) ist unabhängig vom Typ der Basisdaten

Verwendung

interface Foo<T> { ... }
class Bar<T> { ... }
class Baz implements Foo<Integer> { ... }
class Quux<T, U> implements Foo<T> { ... }

// Example
Bar<Integer> b = new Bar<Integer>();
// Ab Java 7 (Diamond operator)
Bar<Integer> b = new Bar<>();
  • Typ-Parameter können nur Referenz-Typen sein
    • Bei Primitives Wrapper benutzen

Einschränkung der Typen

// T muss vom Typ Bar sein
class Foo<T extends Bar> { ... }
// T muss von den Typen Bar, Baz und Quux sein
class Foo<T extends Bar & Baz & Quux> { ... }
  • Zulässige Typen können eingeschränkt werden

Generische Methoden

public class GenericMethods {
    public static <T> T random(T m, T n) {
        return Math.random() > 0.5 ? m : n;
    }

    public static <T> T random(List<T> list) {
        return list.get(Math.round(Math.random() * (list.size - 1)));
    }
}
  • Auch bei nicht-statischen Methoden möglich

Vererbung

// Not OK
List<Object> foos           = new ArrayList<Foo>();

// OK
List<Foo> foos              = new ArrayList<>();
List<?> foos                = new ArrayList<Foo>();
List<? extends Foo> foos    = new ArrayList<Foo>();
  • ? kann als Wildcard verwendet werden

Will it compile?

public static T max(T x, T y) {
    return x > y ? x : y;
}
public static void print(List<? extends Number> list) {
    for (Number n : list)
        System.out.print(n + " ");
    System.out.println();
}

Nein, Ja

Will it compile?

class Shape { /* ... */ }
class Circle extends Shape { /* ... */ }
class Rectangle extends Shape { /* ... */ }
class Node<T> { /* ... */ }

Node<Circle> nc = new Node<>();
Node<Shape>  ns = nc;
class Node<T> implements Comparable<T> {
    // ...
    public int compareTo(T obj) { /* ... */ }
}

Node<String> node = new Node<>();
Comparable<String> comp = node;

Nein, Ja

Will they code?

  • Write a generic method to count the number of elements in a collection that have a specific property (for example, odd integers, prime numbers, palindromes).
  • Write a generic method to exchange the positions of two different elements in an array.
  • Write a generic method to find the maximal element in the range [begin, end) of a list.

Rekursion

Rekursion

Was ist das?

Eine Methode f heißt rekursiv, wenn im Rumpf von f Aufrufe von f vorkommen.

Beispiel

public static long fac(final int n) {
    if (n < 2) {
        return 1;
    } else {
        return n * fac(n - 1);
    }
}

// Und das Ganze nochmal kürzer
public static long fac(final int n) {
    return (n < 2) ? 1 : n * fac(n - 1);
}

Übungsaufgabe

Implementiert binäre Suche auf einem int-Array rekursiv

Musterlösung

Feierabend!

http://xkcd.com/244/