我的程序包含以下类
class Token {
ptivate TokenType t;
// ...
public Token(TokenType t) {
this.t = t;
}
// ...
public TokenType getType() {return t}
}
interface TokenType {}
enum Function implements TokenType {
// ...
LOG {
double apply(double x) {
return Math.log(x);
}
}
// ...
abstract double apply(double x);
}
enum Operation implements TokenType {
// ...
abstract double apply(double x, double y);
}
enum Const implements TokenType {
// no behaviors
}
现在当我想使用它们时我必须这样做
Token t = new Token(Function.LOG);
Function f = (Function) t.getType();
double x = f.apply(1.0);
我需要具有不同 token 类型的 token 列表。让具有不同行为的不同枚举类都实现一个空接口(interface)是一个坏主意吗?我怎样才能避免这里的沮丧?
最佳答案
使 token
通用:
class Token<T extends Enum<T> & TokenType> {
ptivate T t;
// ...
public Token(T t) {
this.t = t;
}
// ...
public T getType() {return t}
}
当然,如果您实际上不需要枚举约束,您可以简化绑定(bind)到的类型变量:
<T extends TypeToken>
然后:
Token<Function> t = new Token<>(Function.LOG);
Function f = t.getType();
double x = f.apply(1.0);
<小时/>
从评论来看,您似乎关心如何设计具有 TokenType
项的异构列表。
您遇到的问题是 apply
方法不是 TokenType
不同实现所共有的接口(interface)的一部分(例如 TokenType
本身)。给定此类实例的列表,您当前必须检查实例的类型,进行强制转换,然后调用适当的方法。
相反,请考虑如何拥有一个通用方法。您正在拿一些 double ;并返回一个双倍。实现此目的的一种方法是使用堆栈,例如
interface DoubleStack {
double pop();
void push(double d);
}
interface TokenType {
void apply(DoubleStack stack);
}
现在您可以实现日志的 apply 方法,其中弹出一次并推送一次;或操作,弹出两次并推送一次。
那么您无需担心类型:您可以简单地在任何实例上调用 apply 方法:
DoubleStack stack = ...;
for (TokenType t : listOfTokenTypes) {
t.apply(stack);
}
关于java - token 类的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48454229/