我的程序包含以下类

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);
}

09-12 12:40