'Self-Circular bounded type parameter
I'm not able to wrap my head around this. I am at dis-ease with this type declaration I came across in our codebase. Can someone please help me understand this?
public interface CodeReviewRequest<Q extends CodeReviewRequest<Q>> {
....
}
Solution 1:[1]
This is actually a common tactic in the Java language. For example, look at the class definition for Enum.
Whenever you have an Interface or an Abstract Class in Java, you can use this circular declaration to assert the following claim: Any class that directly implements/extends me must use either themselves as the type parameter or another type that implements/extends me.
This is particularly useful because it limits what can be placed into the type parameter, while still leaving it open for extension.
For example, consider the following code.
public class ExtendsTest
{
public interface User<Q extends User<Q>> { ... }
public class ReadUser implements User<ReadUser> { ... }
public class ReadWriteUser implements User<ReadWriteUser> { ... }
public class Admin extends ReadWriteUser { ... }
public class StringUser implements User<String> { ... } //this fails because String is not an acceptable cornerstone type
}
By using this tactic, you are essentially creating a gated community of possible types that can be used in the type parameter. That gated community can expand as freely as you like, but they all must implement the interface using either themselves, or another class that implements the interface. And you might notice - the type that sort of acts like the cornerstone (besides the interface) is CommonUser. When using this gated community tactic, you will always end up with one or more types at the top that use this circular declaration to define themselves. Thus, you can have several mini communities within your gated community. It's a powerful way to set boundaries through typing and extension, while still letting things be fairly free and open ended.
EDIT - After a good discussion with @newacct, I should really mention that interface User<Q extends User<Q>> is (as far as I can tell) equivalent to interface User<Q extends User<?>>. So either/or on the syntax. My points about the benefits still stand, but it's important to clarify the syntax.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
