I am trying to understand what the following means?
public class Bar<T extends Bar<T>> extends Foo<T> {
//Some code
}
What is the advantage of doing something like this (e.g. use-case?).
A Generic class simply means that the items or functions in that class can be generalized with the parameter(example T) to specify that we can add any type as a parameter in place of T like Integer, Character, String, Double or any other user-defined type.
Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.
That's a fairly theoretical example, but you could need it in this case:
public class Bar<T extends Bar<T>> extends Foo<T> {
private final T value;
public T getValue() { return value; }
public void method(T param) {
if (param.getValue().equals(someValue)) {
doSomething();
} else {
doSomethingElse();
}
}
}
You would not be able to call param.getValue()
if T were not a Bar
, which it is because T extends Bar<T>
.
This is very similar with the way java.lang.Enum
class is defined:
public abstract class Enum<E extends Enum<E>> implements Comparable<E> {
private final String name;
private final int ordinal;
protected Enum(String name, int ordinal) {
this.name = name; this.ordinal = ordinal;
}
public final String name() { return name; }
public final int ordinal() { return ordinal; }
public String toString() { return name; }
public final int compareTo(E o) {
return ordinal - o.ordinal;
}
}
As the classes defined like this have to be abstract and cannot be instantiated directly, the pattern is useful in constructs similar with the way normal enums are expanded:
// corresponds to
// enum Season { WINTER, SPRING, SUMMER, FALL }
final class Season extends Enum<Season> {
private Season(String name, int ordinal) { super(name,ordinal); }
public static final Season WINTER = new Season("WINTER",0);
public static final Season SPRING = new Season("SPRING",1);
public static final Season SUMMER = new Season("SUMMER",2);
public static final Season FALL = new Season("FALL",3);
private static final Season[] VALUES = { WINTER, SPRING, SUMMER, FALL };
public static Season[] values() { return VALUES.clone(); }
public static Season valueOf(String name) {
for (Season e : VALUES) if (e.name().equals(name)) return e;
throw new IllegalArgumentException();
}
}
Example from book "Java Generics and Collection".
You are basically limiting the kinds of types that Bar
will "deal with" to anything that extends Bar<T>
. In this case, you want to make sure that Bar
is only dealing with extensions of itself - maybe call a method that's private to Bar
. One simple example is that you might use this class to implement a kind of linked list, and iterate over it while doing something that only Bar
can/should do. Let's say you had the following code:
public class Bar<T extends Bar<T>> extends Foo<T> {
private T next;
//Initialize next in constructor or somewhere else
private void doSomethingOnlyBarCanDo(){
//Do it...
}
public void iterate(){
T t = next;
while(t != null){
t.doSomethingOnlyBarCanDo();
t = t.next;
}
}
}
With this kind of a construct, it'd be very easy to iterate over a "chain" of Bar
instances, because each instance would have a reference to the next - recall that T
extends Bar<T>
, so you can refer to it as such.
One typical use case is Wrapper/Decorator pattern. Bar
probably wraps T
that extends Bar
itself. Foo
is just a parametrized class that deals with T
.
public abstract class Foo<T> {
public abstract void foo(T t);
}
public class Bar<T extends Bar<T>> extends Foo<T> {
private T wrapped;
public Bar(T w) {
this.wrapped = w;
}
public abstract void foo(T t) {
// do something
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With