Generika

Generika umožňují vytvářet třídy a metody “on demand” parametrizované nějakou jinou třídou (ale nikoliv např. číslem, což je možné např. v C++, kde se to nazývá “templates” neboli šablony).

Generická třída a rozhraní

Jednoduchý příklad:

/**
 * Generic version of the Box class.
 * @param <T> the type of the value being boxed
 */
public class Box<T> {
    // T stands for "Type"
    private T t;
 
    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

A zde volání

Box<Integer> integerBox = new Box<Integer>();

Jiný a lepší příklad

public interface Pair<K, V> {
    public K getKey();
    public V getValue();
}
 
public class OrderedPair<K, V> implements Pair<K, V> {
 
    private K key;
    private V value;
 
    public OrderedPair(K key, V value) {
	this.key = key;
	this.value = value;
    }
 
    public K getKey()	{ return key; }
    public V getValue() { return value; }
}

inicializace OrderedPair class:

Pair<String, Integer> p1 = new OrderedPair<String, Integer>("Even", 8);
Pair<String, String>  p2 = new OrderedPair<String, String>("hello", "world");

Java 7 zkrátí na

OrderedPair<String, Integer> p1 = new OrderedPair<>("Even", 8);
OrderedPair<String, String>  p2 = new OrderedPair<>("hello", "world");

Pro ty co se neztratili

OrderedPair<String, Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));

Generická metoda

Nemusí být generická celá třída, generickou lze udělat i samotnou metodu:

public class ListCreator {
    public static <T> List<T> createList(T ... elements) {
        List<T> list = new ArrayList<T>(elements.length);
        for (T element : elements) {
            list.add(element);
        }
        return list;
    }
}

Ono <T> před signaturou metody je ekvivalentní stejnému <T> za názvem třídy, akorát negeneralizujeme celou třídu, ale samotnou metodu.

Když generické metody voláme, můžeme buď nechat typ odvodit:

List<Integer> ints = ListCreator.createList(1, 3);
System.out.println(ints);
System.out.println("Types: " + ints.get(0).getClass().getSimpleName() +
        ", " +ints.get(1).getClass().getSimpleName());
List<String> strings = ListCreator.createList("ab", "cd");
System.out.println(strings);
System.out.println("Types: " + strings.get(0).getClass().getSimpleName() +
        ", " +strings.get(1).getClass().getSimpleName());

Produkuje

[1, 3]
Types: Integer, Integer
[ab, cd]
Types: String, String

Nebo jej ručně specifikovat voláním ve tvaru:

List<Integer> ints = ListCreator.<Integer>createList(1, 3);

Zde ale postrádá smysl, protože není jiná možnost než tato.

courses/b0b36pjv/tutorials/04/generika.txt · Last modified: 2021/03/03 11:08 by seredlad