在类结构中查找正确的子类

时间:2012-11-27 23:54:11

标签: java class polymorphism subclass

我有一个类,我们称之为ClassA,以及它的一些子类,以及这些类的后续子类。 ClassA,并且它下面的每个类在其构造函数中的参数处都需要String。我有一堆String个对象需要“转换”为ClassA的子类。

我正在做的当前方式是使用isType(String)方法来检查String是否是该子类的实例,但是使用巨大的if-else似乎是非常糟糕的编程技术或switch-case语句,以查找ClassA所属的String的正确类型。它有一个常见的方式来进入子类结构,还是我一直这样做的方式好吗?

这样做的目的是我正在编写脚本语言(用于有趣的项目),我需要能够识别出什么是东西。 (数据类型)

示例代码:

public static boolean isType(String data) {
    data = data.trim();
    return edu.ata.script.data.Boolean.isType(data)
            || edu.ata.script.data.Integer.isType(data)
            || edu.ata.script.data.Double.isType(data)
            || DATA_STORAGE.contains(data)
            || ReturningMethod.isType(data)
            || edu.ata.script.data.String.isType(data);
}

public static Data get(String data) {
    data = data.trim();
    /*:)*/ if (edu.ata.script.data.Boolean.isType(data)) {
        return edu.ata.script.data.Boolean.get(data);
    } else if (edu.ata.script.data.Integer.isType(data)) {
        return edu.ata.script.data.Integer.get(data);
    } else if (edu.ata.script.data.Double.isType(data)) {
        return edu.ata.script.data.Double.get(data);
    } else if (DATA_STORAGE.contains(data)) {
        return (Data) DATA_STORAGE.get(data);
    } else if (ReturningMethod.isType(data)) {
        return ReturningMethods.getMethodValue(data);
    } else if (edu.ata.script.data.String.isType(data)) {
        // Last option because everything is accepted.
        return edu.ata.script.data.String.get(data);
    } else {
        throw new RuntimeException("Could not parse data - " + data);
    }
}

2 个答案:

答案 0 :(得分:1)

我确实理解了完全不同的东西,所以我正在重新编辑这个答案。

我怀疑你正在使用某种输入脚本或其他东西,并且edu.ata.script.data.*是你正在编写的ClassB,ClassC等,他们知道如何将东西从一种格式转换为另一种格式。 ..(这只是猜测)

我建议删除get(String data)方法中的所有if if else,即实现chain of responsability。这样你可以有一个链在一个List中注册几个edu.ata.script.data。*然后你遍历那个列表,直到其中一个为isType(字符串)返回true,知道你要使用哪个子类处理字符串。

要删除isType(String data)方法中的OR列表有点棘手,可能这有点过于引人注目,但您可以执行以下操作:

  1. 在类路径中查找可从您的类
  2. 分配的类
  3. 然后当你要检索所有可由你自己分配的类时,你必须通过反射调用每个类的isType才能知道结果

    我知道你可能会发现自己在第一点上有点迷失,最好的方法是从Stripes Framework查看ResolverUtil类,他们在方法loadImplementationsFromContextClassloader

答案 1 :(得分:0)

看起来您正在尝试将字符串解析为正确子类的实例,方法是将其传递给每个子类的isType方法,直到有人说它可以处理它。我希望每个子类都注册一个解析器对象,该对象可以检查字符串并在可能的情况下生成相应子类的初始化实例。

解析器的接口:

package edu.ata.script.data;

interface ScriptParser {
    public boolean isType(String data);
    public Data    get(String data) throws UnparsableException;
}

示例数据子类:

package edu.ata.script.data;

public class Boolean extends Data {

// Empty constructor for reflection purposes
public Boolean() {};

public Boolean(String data) {
    // Initialise from string
}

public ScriptParser getParser() {
    return new ScriptParser() {
        public boolean isType(String data) {
           return "true".equals(data) || "false".equals(data);
        }

        public Data get(String data) throws UnparsableException {
            if (isType(data)) {
                return new edu.ata.script.data.Boolean(data);
            } else {
                throw new UnparsableException(data);
            }
        }
    };
}

}

然后,您可以在解析之前将类列表构建到集合中:

List<ScriptParser> parsers = new LinkedList<>();
parsers.add(new edu.ata.script.data.Boolean().getParser());
parsers.add(new edu.ata.script.data.Integer().getParser());
parsers.add(new edu.ata.script.data.Double().getParser());
...

上述也可以通过反思实现。

然后,无论您最终支持多少数据类型,都可以使用简单的循环解析数据:

public Data get(String data) throws SyntaxErrorException {
    for (ScriptParser sp:parsers) {
        if (sp.isType(data)) {
            try {
                return sp.get(data);
            } catch (UnparsableException e) {
                // This shouldn't happen, but better safe than sorry!
                e.printStackTrace();
            }
        }
    }
    throw new SyntaxErrorException(data);
}