我正在尝试为我的程序设置一个多态的ExportRule系统,但是在弄清楚如何从配置文件构造所需的ExportRule时遇到麻烦,该配置文件通过String在文件的顶部定义了ExportRule。

我一直想做这样的事情:

private ExportRule loadExportRule(String fileName) throws IOException, InvalidConfigurationException, FileNotFoundException{
    if(fileName == null) {
        throw new NullPointerException("fileName cannot be null!");
    }
    YamlConfiguration exportRuleConfig = new YamlConfiguration();
    exportRuleConfig.load(getFilePath(fileName));

    return ExportRules.fromString(exportRuleConfig.getString("exportRule")).fromYamlConfiguration(exportRuleConfig);
}


其中ExportRules是将字符串映射到实际.class(扩展ExportRule)的枚举,然后将调用静态fromFileConfiguration()工厂方法以从文件生成ExportRule,如下所示:

exportRule: nameOfExportRule
//all the configurationstuff for the rule


我遇到的问题是如何实际调用fromFileConfiguration()方法,因为它是静态方法,因此Java不允许我通过ExportRule接口保证它的存在

是否有一种干净的方法来实现这样的目标,还是我必须在枚举中为每个ExportRule做某种switch语句?

编辑:

谢谢glee8e!

这是我的枚举:

public enum ExportRules {
COMMENT_CONCAT("CommentConcat") {
    @Override
    public ExportRule fromFileConfiguration(FileConfiguration fileConfiguration) throws InvalidConfigurationException {
        return CommentConcat.fromFileConfiguration(fileConfiguration);
    }
};

private String name;

ExportRules(String name) {
    this.name = name;
}

public abstract ExportRule fromFileConfiguration(FileConfiguration fileConfiguration) throws InvalidConfigurationException;

public String getName() {
    return name;
}

public static ExportRules fromString(String str) {
    for(ExportRules rule : ExportRules.values()) {
        if(str.equalsIgnoreCase(rule.getName())) return rule;
    }
    return null;
}

}

最佳答案

多态不是用于静态对象,而是用于实例方法,至少在Java中是如此。将您的fromFileConfiguration设为抽象实例方法,并将其实现为单个常量:

public enum ExportRules {
    A_RULE {
         @Override public ExportRule fromFileConfiguration(YamlConfiguration c) {...}
    },
    //...
    public abstract ExportRule fromFileConfiguration(YamlConfiguration c);

}


请记住,java枚举也是普通的类。他们可以实现接口,具有抽象方法等。但是,您不能拥有非Enum超类和非私有构造函数。

附注:对于Java8,由于该枚举只有一个抽象方法,因此您可以使用Function而不是创建许多子类,如下所示:

public enum ExportRules {
    A_RULE((c) -> {//...}),
    //...
    private final Function<YamlConfiguration, ExportRule> func;
    private ExportRules( Function<YamlConfiguration, ExportRule> fun) {
        func = fun;
    }

    public ExportRule fromFileConfiguration(YamlConfiguration c) {
        return func.apply(c);
    }

}


这不是经典的多态性,但可以完成工作并减少产生的废品。

07-28 04:10