JAVA VIBES - Solid Code Design – Part 6 – Contravariance
Sanjoy Kumar Malik .
?? Generative AI and Agentic AI Enthusiast ?? Senior Software Architect ?? Professional AWS Architect ?? All views are my own
In Part 4 and Part 5, I introduced you with the concept of invariance and covariance respectively. In this article, I will cover contravariance.
We will use the same type hierarchies and code from the Part 5. For your convenience, I will provide the type hierarchies once again here.
Contravariance
To take advantage of covariance, we use?lower bounded wildcards?as follows.
The expression “? super EaterB” represents type EaterB or any supertype of EaterB. Here EaterB is the lower bound. Since we are sure about the supertype EaterB, we can logically assign any subclass of EaterB to “? super EaterB”. The Figure 1 below will clarify the concept.
Contravariance means: for some generic type G, G<X> is subtype of G<? super Y> when X is a supertype of Y. For example, MyContainer<EaterA> is a subtype of MyContainer<? super EaterB>. Here,?MyContainer<? super EaterB>?is a?contravariant instantiation?of MyContainer and EaterB is the lower bound.
Inside a contravariant structure, we can put objects belonging to a particular type hierarchy where the lower bound is the root of the hierarchy.
Consider a type hierarchy where EaterB is root of the hierarchy.
The contravariant structure MyContainer<? super EaterB> will be happy to contain the elements of type EaterB or subtype of EaterB. It means we can easily add element of type EaterB, EaterC, and EaterG via refEbContraContainer. Therefore, the code below is perfectly OK.
领英推荐
Now we will try to retrieve objects using the reference variable refEbContraContainer. Have a look at the below code snippet.
The above three lines give same kind of error. For example, Line 1 gives the below error:
Type mismatch: cannot convert from capture#8-of ? super EaterB to EaterB
Similarly, Line 2 and Line 3 give the below errors respectively.
Type mismatch: cannot convert from capture#9-of ? super EaterB to EaterC.
Type mismatch: cannot convert from capture#10-of ? super EaterB to EaterG
From the above errors, we understand that the container MyContainer<? super EaterB> can contain any elements of either type EaterB or subtype of EaterB, but we cannot say exactly which type it is. It may be EaterB or EaterC or EaterG. Therefore, we cannot assign any retrieved element from the container MyContainer<? super EaterB> to a specific type like EaterB or EaterC or EaterG. But we can assign the retrieved value to Object (since Object is the superclass of any class eventually).
Conclusion
We use lower bounded wildcards (? super SomeLowerBound) for contravariance. Remember, we only put data into a contravariant structure. We cannot read anything out of it apart from Object
That’s all for contravariance for the time being.
CXO Relationship Manager
11 个月thank you so much for sharing. it's amazing article.
.
1 年(That spying related post of yours, is not accessible to me now ?? )
Realtor Associate @ Next Trend Realty LLC | HAR REALTOR, IRS Tax Preparer
1 年Thanks for posting.