我的程序包含以下类
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
通用:
class Token<T extends Enum<T> & TokenType> {
ptivate T t;
// ...
public Token(T t) {
this.t = t;
}
// ...
public T getType() {return t}
}
当然,如果您实际上不需要枚举约束,则可以简化绑定到以下类型的类型变量:
<T extends TypeToken>
然后:
Token<Function> t = new Token<>(Function.LOG);
Function f = t.getType();
double x = f.apply(1.0);
从评论看来,您似乎在担心如何设计
TokenType
项目的异构列表。您在这里遇到的问题是
apply
方法不是TokenType
的不同实现(例如TokenType
本身)所共有的接口的一部分。给定此类实例的列表,您当前必须检查实例的类型,进行强制转换,然后调用适当的方法。相反,请考虑如何使用通用方法。您正在进行一些双打;并返回一个双。一种实现此方法的方法是使用堆栈,例如
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);
}