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



我有一个类,我们称之为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);
}
}

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

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

我建议去掉get(String data)方法中的所有if-then-else,那就是实现一个响应链。这样,你就可以有一个在List中注册几个edu.ata.script.data.*的链,然后你在该列表中迭代,直到其中一个对isType(字符串)返回true,知道你想用哪个子类来处理字符串。

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

  1. 在类路径中查找可从类分配的类

  2. 然后,当您检索所有可由自己分配的类时,您必须通过反射调用每个类的isType才能知道结果

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

看起来你正试图将一个字符串解析为正确子类的实例,方法是将其传递给每个子类的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);
}

最新更新