PECS (Producer Extends Consumer Super) - nus-cs2030/2021-s1 GitHub Wiki
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 isList<? 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 isList<? 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 butConsumer<? 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.
- the reason why we need this
- Consumer andThen(Consumer<? super T> after)
-
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: