【发布时间】:2015-10-24 14:44:09
【问题描述】:
假设我想要一个这样的抽象类:
public abstract Operator {
public int[] operands;
public Operator(int[] operands) {
this.operands = operands;
}
public abstract int getOperatorResult();
}
还有一些从它扩展而来的运算符,例如:
public class Add extends Operator {
public Add(int[] operands) {
super(operands);
}
public int getOperatorResult() {
return operands[0] + operands[1];
}
}
还有一个 OperatorCreator,它获取类似 "1+1" 的表达式并返回适当的 Operator 的子类(在本例中为 Add):
public class OperatorCreator {
public static Operator getInstance(String expr) {
...
}
}
主要问题: 我想让其他人通过扩展 Operator 类来设计自己的运算符。并以多态方式使用它们的运算符。像这样:
public class Main {
public static void main(String[] args) {
Operator op = OperatorCreator.getInstance("1-2");
System.out.println(op.getOperatorResult());
}
}
假设 OperatorCreator 知道 Operator 子类的 .class 文件的位置,并在运行时使用反射加载这些子类。 但是 OperatorCreator 还必须知道一件事:它还必须知道这些子类的运算符符号,以便在例如给出“1+1”时返回一个 Add 对象。所以任何运算符的子类都可以有一个静态方法:“getSymbol”,它返回运算符的符号。但有一个问题。如果有人扩展 Operator 并且不提供“静态 getSymbol”,她的代码将成功编译,但不会为 OperatorCreator 提供一种机制来了解她的新 Operator 子类的符号,这会导致运行时问题。而且我不想让 getSymbol 成为 Operator 的抽象方法来强制子类实现它,因为我不想创建子类的实例来获取它的符号。如何强制子类在加载时注册其符号?
【问题讨论】:
-
如果您的 JDK 是 8 版,那么在 Java 8 中,接口可以具有静态方法,以及具有默认实现的可覆盖方法。他们仍然不能有实例字段。这些功能是 lambda 表达式支持的一部分。但如果你的 JDK
-
感谢您提供有关 JDK 8 的这些有趣信息。但我的程序将在较旧的 JRE 上运行。 @RaminOmrani
-
该方法根本不应该是静态的。
-
“我不想创建子类的实例”。您打算如何在不创建子类实例的情况下调用 getOperatorResult 方法? getInstance 方法必须创建一个适当的实例。我知道这不能回答您的问题,但不创建子类的实例无论如何都不是这里的选择。看我的回答。
-
我说我不想让自己创建一个实例只是为了调用getSymbol。 @CKing
标签: java inheritance design-patterns reflection static