对不起标题:-/
我为计算器编写了一个解析器。它有效,但我不喜欢我的 token 层次结构。解析器应该不知 Prop 体的数字类型,例如它应该可以配置为 Double、BigDecimal 等。所以我有一个通用的 token 接口(interface)
public interface Token<T> { }
public class NumToken<T> {
private final value T;
...
}
public class OperatorToken<T> {
...
}
现在我的问题是如何处理无论数字类型如何都相同的“结构” token ,例如括号和分隔符。泛型参数不仅在那种情况下无用,它还阻止我为该类型使用枚举。但是,枚举将非常有用,例如它可以在 switch 语句中使用。
现在我已经“解决”了这个问题:
public enum CharToken implements Token<Object> {
OPEN('('),
CLOSE(')'),
SEPARATOR(','),
EOL(';');
private final char ch;
private CharToken(char ch) {
this.ch = ch;
}
}
这行得通,但迫使我在解析器的任何地方都写类似 List<Token<? super T>>
的东西,并假设所有其他类型实际上是 Token<T>
当我施法时。很明显,我在这里使用的是类型系统:从类型理论的角度来看,我碰壁了,因为 Java 没有像 Scala 中的“Nothing”那样的“底层”类型(这将是一个完美的选择)。有更好的解决方案吗?
[澄清]
T 是我的解析器应该处理的预期数字类型,而不是 token 的“内容”。例如。对于 OperatorToken<T>
我有一个方法 calc(T op1, T op1)
.而且我希望能够通过 T 参数化整个解析器,因此它使用的所有 token 都需要相同的 T(好吧,如果你不像我那样使用 super
作弊),因此 CharToken implements Token<Character>
不会很有用。
最佳答案
JDK 中使用的解决方案(例如 java.util.Collections.emptyList()
)正在利用删除 - 类型参数并不真正存在,因为您可能还记得 - 并为方法键入参数推断:
@SuppressWarnings("unchecked")
public enum CharToken implements Token { // Note: No type parameter specified!
OPEN('('),
CLOSE(')'),
SEPARATOR(','),
EOL(';');
public static <T> Token<T> open(){ return OPEN; }
public static <T> Token<T> close(){ return CLOSE; }
public static <T> Token<T> separator(){ return SEPARATOR; }
public static <T> Token<T> eol(){ return EOL; }
private final char ch;
private CharToken(char ch) {
this.ch = ch;
}
}
// Usage:
Token<BigDecimal> bdOpen = CharToken.open();
Token<Integer> intOpen = CharToken.open();
虽然看起来不是很漂亮,但至少它很容易使用。 (为了简洁起见,您可能希望将枚举封装在一个只公开通用方法的类中。)
关于java - 如何将非泛型类集成到泛型层次结构中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4213050/