【问题标题】:Java - Using Generics to Create a Fluent InterfaceJava - 使用泛型创建流畅的接口
【发布时间】:2014-06-11 21:15:03
【问题描述】:

在我当前的任务中,我必须为测试用例构建一个新的 SchemaArtifact 对象,其中填充了递归 Field 对象(两个自定义类)。我还需要使用流畅的界面来执行此操作。问题是我的 build() 函数(在树中弹出一层)如果调用字段位于顶层,则应返回根 SchemaArtifact,如果它是子字段,则应返回其父级。我知道这可能听起来令人困惑,所以希望一些示例代码可以解决它:

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;
        }
    }
}

如您所见,我尝试使用泛型返回多种类型,但是当我尝试一次添加多个字段时,我得到“方法 addField(Field) 未定义对象类型”。我还尝试使用包装器接口,这需要稍后进行不必要的转换;和单独的 buildToSchema()/buildToField() 方法,这可行,但会使创建多个模式更加混乱。

说了这么多,我有没有办法让单一的 build() 方法同时返回 SchemaArtifact 和 Field?

谢谢你,
泰勒

【问题讨论】:

  • 1) #addField 中缺少返回类型。 2) T 应该是什么? 3) parentschema 没有在 Field 中声明。
  • 固定 1 和 3。RE #2:我试图实现类似答案here 的东西,但我可能以某种方式搞砸了。我相信使用 T 意味着 build() 正在返回一个对象,这就是为什么当我尝试在它之后使用 addField() 时出现错误。

标签: java generics fluent


【解决方案1】:

build() 的返回类型必须在编译时知道。在这种情况下,返回对象的类取决于运行时条件,因此在编译时无法知道。

两种可能性:

  • 您知道什么时候会收到FieldSchemaArtifact。在这种情况下,您应该使用两种单独的方法并在适当的情况下使用它们。
  • 您不知道该期待什么类型。在这种情况下,您应该使用接口。

你也可以这样做:

Field field = new SchemaArtifact()
        .addField(new Field("FirstName"))
            .addField(new Field("Nickname")).build();
SchemaArtifactschema = field.build();

这将强制编译器推断正确的类型,但这与使用两种不同的方法相同,只是类型安全性较低(如果使用错误的类型,则会出现ClassCastException)。

【讨论】:

  • 感谢您的回复。我最终创建了一个IFluentSchema 接口来链接两者,所以我可以用一种方法返回任何一种类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-21
  • 2011-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多