Ich stieß auf PECS (kurz für Produzent extends
und Verbraucher super
), während ich mich über Generika informierte.
Kann mir jemand erklären, wie man PECS einsetzt, um die Verwirrung zwischen extends
y super
?
Ich stieß auf PECS (kurz für Produzent extends
und Verbraucher super
), während ich mich über Generika informierte.
Kann mir jemand erklären, wie man PECS einsetzt, um die Verwirrung zwischen extends
y super
?
Voraussetzungen für das Verständnis:
Nehmen wir an, wir haben einen Typ, der einen generischen Typparameter T annimmt, zum Beispiel List<T>
. Beim Schreiben von Code kann es von Vorteil sein, auch Sub- oder Supertypen unseres generischen Typparameters T zuzulassen. Dies lockert die Einschränkungen für den Nutzer der API und kann den Code flexibler machen.
Sehen wir uns zunächst an, was wir gewinnen, wenn wir diese Einschränkungen lockern. Nehmen wir an, wir haben die folgenden 3 Klassen:
class BaseAnimal{};
class Animal extends BaseAnimal{};
class Duck extends Animal{};
und wir bauen eine öffentliche Methode, die eine list<Animal>
List<? super Animal>
anstelle von List<Animal>
können wir nun weitere Listen einfügen, um die Anforderungen unserer Methode zu erfüllen. Wir können nun entweder List<Animal>
o List<BaseAnimal>
sogar List<Object>
List<? extends Animal>
anstelle von List<Animal>
können wir nun weitere Listen einfügen, um die Anforderungen unserer Methode zu erfüllen. Wir können nun entweder List<Animal>
o List<Duck>
Dies bringt jedoch die folgenden 2 Einschränkungen mit sich:
List<? super Animal>
wir kennen nicht die genaue Art der List<T>
wird es sein. Es könnte sich entweder um eine Liste von List<Animal>
o List<BaseAnimal>
o List<Object>
. Wir haben keine Möglichkeit, das zu wissen. Das bedeutet, dass wir nie einen Wert aus dieser Liste erhalten können, weil wir nicht wissen, was der Typ sein wird. Wir können jedoch jeden Datentyp eingeben, der Animal
oder erweitert sie in die List
. Denn wir können nur Daten in den List
wird es als Verbraucher von Daten.List<? extends Animal>
anstelle von List<Animal>
. Wir wissen auch nicht, um welchen Typ es sich genau handelt. Es kann entweder sein List<Animal>
o List<Duck>
. Wir können nicht etwas zum List
denn wir können nie mit Sicherheit wissen, um welchen Typ es sich handelt. Wir können jedoch etwas herausziehen, weil wir immer wissen, dass alles, was aus der Liste kommt, ein Untertyp von Animal
. Denn wir können nur Daten aus dem List
heißt es eine Hersteller von Daten.Hier ist ein einfaches Programm, um die Lockerung der Typbeschränkungen zu veranschaulichen:
import java.util.ArrayList;
import java.util.List;
public class Generics {
public static void main(String[] args) {
Generics generics = new Generics();
generics.producerExtends(new ArrayList<Duck>());
generics.producerExtends(new ArrayList<Animal>());
generics.consumerSuper(new ArrayList<Object>());
generics.consumerSuper(new ArrayList<Animal>());
}
// ? extends T is an upper bound
public void producerExtends (List<? extends Animal> list) {
// Following are illegal since we never know exactly what type the list will be
// list.add(new Duck());
// list.add(new Animal());
// We can read from it since we are always getting an Animal or subclass from it
// However we can read them as an animal type, so this compiles fine
if (list.size() > 0) {
Animal animal = list.get(0);
}
}
// ? extends T is a lower bound
public void consumerSuper (List<? super Animal> list) {
// It will be either a list of Animal or a superclass of it
// Therefore we can add any type which extends animals
list.add(new Duck());
list.add(new Animal());
// Compiler won't allow this it could potentially be a super type of Animal
// Animal animal = list.get(0);
}
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
6 Stimmen
Eine sehr gute Erklärung mit einem Beispiel @ youtube.com/watch?v=34oiEq9nD0M&feature=youtu.be&t=1630, das erklärt
super
Teil, sondern gibt eine Vorstellung von einem anderen.