Polymorphie

poly-morph = viel-gestaltig

ein Bezeichner (z. B. Unterprogramm-Name) mit mehreren Bedeutungen

Arten der Polymorphie:

Beispiel: Überladung im Argumenttyp:
static void p (int x, int    y) { ... }
static void p (int x, String y) { ... }
p (3, 4); p (3, "foo");
keine Überladung nur in Resultattyp, denn...
static int    f (boolean b) { ... }
static String f (boolean b) { ... }

parametrische Polymorphie:

class C {
   static T id<T> (T x) { return x; }
}

string foo = C.id<string> ("foo");
int    bar = C.id<int>    (42);

class Pair<A,B> {
  final A first; final B second;
  Pair(A a, B b) 
    { this.first = a; this.second = b; }
}
Pair<String,Integer> p = 
    new Pair<String,Integer>("foo", 42);
int x = p.second + 3;
vor allem für Container-Typen (Liste, Menge, Keller, Schlange, Baum, ...)

class C {
  static <A,B> Pair<B,A> swap (Pair<A,B> p) { 
    return new Pair<B,A>(p.second, p.first);
  } }
Pair<String,Integer> p = 
    new Pair<String,Integer>("foo", 42);
Pair<Integer,String> q = 
    C.<String,Integer>swap(p);
Typargumente können auch inferiert werden:
Pair<Integer,String> q = C.swap(p);

Anwendung: Sortieren mit Vergleichsfunktion als Parameter

using System; class Bubble {
  static void Sort<T> 
    (Func<T,T,bool> Less, T [] a) { ...
      if (Less (a[j+1],a[j])) { ... } } 
  public static void Main (string [] argv) {
    int [] a = { 4,1,2,3 };
    Sort<int> ((int x, int y) => x <= y, a);
    foreach (var x in a) Console.Write (x);
} }
Ü: (allgemeinster) Typ und Implementierung einer Funktion Flip, die den Vergleich umkehrt: Sort<int> (Flip( (x,y)=> x <= y ), a)

Wenn man einen generischen Typparameter nur einmal braucht, dann kann er ? heißen.

List<?> x = Arrays.asList
    (new String[] {"foo","bar"});
Collections.reverse(x);
System.out.println(x);

jedes Fragezeichen bezeichnet einen anderen (neuen) Typ:

List<?> x = Arrays.asList
    (new String[] {"foo","bar"});
List<?> y = x;
y.add(x.get(0));

2015-08-17