Reputation: 83
In my current assignment, I have to build a new SchemaArtifact object filled with recursive Field objects (both custom classes) for a test case. I also need to do this using a fluent interface. The problem is that my build() function (pops up one level in the tree) should either return the root SchemaArtifact if the calling field is at the top level or return its parent if it is a child field. I know this might sound confusing, so hopefully some example code can clear it up:
public class SchemaHelper{
public SchemaArtifact makeSchema(){
return new SchemaArtifact()
.addField(new Field("FirstName"))
.addField(new Field("Nickname")).build()
.build()
.addField(new Field("LastName")).build();
}
}
public class SchemaArtifact{
private Map<String, Field> fields = new Map();
public addField(Field f){
this.fields.put(field.id, f);
return f;
}
}
public class Field{
public String id;
private Map<String, Field> fields = new Map(); //children
private Field parent; //null if parent is just the main schema
private SchemaArtifact schema; //schema that this Field belongs to
public Field(String id){
this.id = id;
}
public Field addField(Field f){
this.fields.put(field.id, f);
return f;
}
public <T> T build(){
if(this.parent != null){
return (T)this.parent;
}else{
return (T)this.schema;
}
}
}
As you can see, I tried using generics to return multiple types, but I get "The method addField(Field) is undefined for the type Object" when I try adding more than one Field at once. I also tried using a wrapper interface, which required needless casting later; and separate buildToSchema()/buildToField() methods, which works, but makes creating multiple schemas down the line more confusing.
With all that said, is there a way for me to get the singular build() method to return both a SchemaArtifact and a Field?
Thank you,
Tyler
Upvotes: 0
Views: 278
Reputation: 7393
The return type of build()
must be known at compile time. In this case, the class of the returned object depends on a runtime condition, so it can't be known at compile time.
Two possibilities :
Field
or a SchemaArtifact
. In this case you should use two separates methods and use them where appropriate.You could also to this :
Field field = new SchemaArtifact()
.addField(new Field("FirstName"))
.addField(new Field("Nickname")).build();
SchemaArtifactschema = field.build();
This will force the compiler to infer the right types, but it's the same as using two different methods, just less type safe (there will be a ClassCastException
if you use the wrong type).
Upvotes: 1