So I have the following code that I have been playing around with to try to understand recursive generics.
class Person
{
public String name;
public String position;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", position='" + position + '\'' +
'}';
}
}
//This is called a recursive generic.
class PersonBuilder<SELF extends PersonBuilder<SELF>>
{
protected Person person = new Person();
public SELF withName(String name)
{
person.name = name;
//System.out.println(this.getClass());
//System.out.println(self().getClass());
return self();
}
public Person build()
{
return person;
}
protected SELF self()
{
return (SELF) this;
}
}
class EmployeeBuilder extends PersonBuilder<EmployeeBuilder>
{
public EmployeeBuilder worksAt(String position)
{
person.position = position;
return self();
}
@Override
protected EmployeeBuilder self()
{
return this;
}
}
class Demo1
{
public static void main(String[] args) {
EmployeeBuilder eb = new EmployeeBuilder();
Person richard = eb.withName("Richard")
.worksAt("Programmer")
.build();
System.out.println(richard);
PersonBuilder pb = new PersonBuilder<>();
Person bob = pb.withName("Bob").build();
}
}
I have a few questions related to the above implementation.
Why is this called a recursive generic? Is it recursive because the Parent class has a Child class as the generic? I understand that the goal is that we need to return an Object of the Child class in the inherited withName method to be able to call methods in both the Child and Parent classes.
What is the difference between
PersonBuilder<SELF>
and PersonBuilder? For instance, I created a PersonBuilder object in the main method withPersonBuilder pb = new PersonBuilder<>()
. What is implied in the <> here if it's just the Parent class?
- Does the generic "disappear" somehow? I am asking this because when I printed class using this.getClass() I only got PersonBuilder as the class, which is why I am thinking somehow the generic is gone. On the other hand, since the class signature has the generic attached to it, I have a feeling it must be lurking somewhere.
- What is the difference if I changed the class signature to
class PersonBuilder<SELF extends PersonBuilder>
? I ran the code with this change and it still worked. I have a feeling it has something to do with being consistent, but I do not have enough insight into what is going on to see how this makes a difference.
Thanks for your help.