Skip to content

PECS (Producer Extends Consumer Super)

bingmeow1999 edited this page Nov 30, 2020 · 4 revisions

PECS (aka Get and Put principle)

Take AY17/18 Sem 2 Final Part I 2. as an example:

  • pieces.add(new Queen()); (put)
    Consider a storage box with all kinds of toys, which is List<? super ChessPiece>. We can definitely add chess pieces “like Queen” into the storage box; however, we are not sure what we can get from the storage box (maybe even not a chess piece).

  • ChessPiece p = pieces.remove(0); (get)
    Imagine here are some “Queen” chess pieces, which is List<? extends ChessPiece>. From this declaration, we only know it’s a collection of a particular kind of chess pieces, but from the declaration, we don’t really know what is in it. If we can get from that list, we can definitely get a chess piece; however, we cannot add to it, since we might try to add a “King” into a bunch of “Queen”.

  • Consumer

    • consumer (which takes some objects and consume them, such as the add method), we expect it to take objects of type no more than(superclasses) the type T we specified, because the process of consuming needs possibly any member(variables, methods etc.) of the type it wants, and we want to ensure that type T satisfy all the members the consumer requires.
    • Use a super wildcard when you only put values into a structure.
    • You want to add things to the collection.
      • Then the list is a consumer, so you should use a Collection<? super Thing>.
      • The reasoning here is that unlike Collection<? extends Thing>, Collection<? super Thing> can always hold a Thing no matter what the actual parameterized type is. Here you don't care what is already in the list as long as it will allow a Thing to be added; this is what ? super Thing guarantees.
    • example:
      • Consumer andThen(Consumer<? super T> after)
        • the reason why we need this ? super T is that: when we are combining two Consumers using the method andThen, suppose that the former Consumer takes an object of type T, we expect the later to take a object of type no more than T so it would not try to access any member that T doesn't have.
        • Therefore, rather than simply writing Consumer<T> after but Consumer<? super T> after, we allow the former consumer (of type T) to be combined with a consumer that takes an object not exactly of type T, but maybe superclass of T, by the convenience of Contravariance.
  • Producer

    • producer, which produces objects for us (like the get method), has to supply objects of type no less than the specified type T so that we can access any member that T has on the object produced.
    • Use an extends wildcard when you only get values out of a structure.
    • You want to go through the collection and do things with each item.
      • Then the list is a producer, so you should use a Collection<? extends Thing>.
      • The reasoning is that a Collection<? extends Thing> could hold any subtype of Thing, and thus each element will behave as a Thing when you perform your operation. (You actually cannot add anything to a Collection<? extends Thing>, because you cannot know at runtime which specific subtype of Thing the collection holds.)

More Information: https://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super

Great practice for finals! There were a few meaningful discussions about PECS regarding practice papers:

Clone this wiki locally