“PECS” in Java — Easy visualization
Have you ever heard about “PECS”?
If you have, you would have ended up googling it and found…
“Producer Extends, Consumer Super.”
Eh? What exactly are Producer and Consumer…? Actually, it’s not easy to understand this concept at once.
So, let’s visualize this concept so that we can understand it easily!
When you read some codes written in Java, there is a high chance that you ran into this weird looking stuff.
<? super SomeType>
or
<? extends SomeType>
Obviously it’s related to the concepts of ‘Generic types’ and ‘Inheritance’. All right, at least we know what ‘super’ and ‘extends’ are.
So basically the <? super SomeType>
is an “undefined(yet)” type, but that undefined type should be a superclass of the ‘SomeType’ class.
The same goes for <? extends SomeType>
. It’s a type that should extend the ‘SomeType’ class (it should be a child class of the ‘SomeType’ class).
Now, let’s think about the concept of class inheritance in a Venn diagram:
Mammal class extends Animal class (Animal class is a superclass of Mammal class).
Cat/Dog class extends Mammal class (Mammal class is a superclass of Cat/Dog class).
This is not very difficult, right? :)
Then, let’s think about the ‘circles’ in the above diagram as a ‘box’ that has a physical volume.
You CAN’T put a bigger box into a smaller one.
You can ONLY put a smaller box into a bigger one.
When you say <? super SomeType>
, you wanna describe a ‘box’ that is the same size or bigger than the ‘SomeType’ box.
If you say <? extends SomeType>
, then you wanna describe a ‘box’ that is the same size or smaller than the ‘SomeType’ box.
Now you might think, “Ok, Ok. I understand everything, so what is PECS anyway?”
We’re almost done! :) we just need to know what are ‘Producer’ and ‘Consumer’.
An example of a ‘Producer’ is a List which we only read from.
An example of a ‘Consumer’ is a List which we only write into.
Just keep in mind this:
- We ‘read’ from a ‘producer’, and take that stuff into our own box.
- We ‘write’ our own box into a ‘consumer’.
So, we need to read(take) something from a ‘producer’ and put that into our ‘box’. This means that any boxes taken from the producer should NOT be bigger than our ‘box’. That’s why “Producer Extends.”
“Extends” means a smaller box(smaller circle in the Venn diagram above). The boxes of a producer should be smaller than our own box, because we are gonna take those boxes from the producer and put them into our own box. We can’t put anything bigger than our box!
Also, we need to write(put) our own ‘box’ into a ‘consumer’. This means that the boxes of the consumer should NOT be smaller than our own box. That’s why “Consumer Super.”
“Super” means a bigger box(bigger circle in the Venn diagram above). If we want to put our own boxes into a consumer, the boxes of the consumer should be bigger than our box!
Let’s visualize this:
Also, we can consider “Consumer”:
Now we can easily understand this example:
public class Collections {
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (int i = 0; i < src.size(); i++)
dest.set(i, src.get(i));
}
}
In the above example, we want to read(take) something from src
and write(put) them into dest
. So the src
is a “Producer” and its “boxes” should be smaller(more specific) than some type T
.
Vice versa, the dest
is a “Consumer” and its “boxes” should be bigger(more general) than some type T
.
If the “boxes” of the src
were bigger than that of the dest
, we couldn’t put those big boxes into the smaller boxes the dest
has.
Great!! Now we got the concept of PECS, and it should be much clearer what “PECS” means:
“Producer Extends(should be smaller), Consumer Super(should be bigger).”
Wanna give this article some claps? :) Thanks!!