905 Stimmen

Was ist PECS (Producer Extends Consumer 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 ?

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.

0voto

Willem van der Veen Punkte 26043

PECS: Produzent erweitert und Konsument super

Voraussetzungen für das Verständnis:

  • Generika und generische Platzhalter
  • Polymorphismus, Subtypisierung und Supertypisierung

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>

  1. Wenn wir eine Super 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>
  2. Wenn wir ein extends verwenden 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:

  1. Wenn wir einen Supertyp wie 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.
  2. Wenn wir ein extends verwenden 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.com

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.

Powered by:

X