设计一个抽象 class 以便任何人都可以扩展它并以多态方式使用扩展的 class

design an abstract class so that any one can extend it and use the extended class polymorphically

我想要一个这样的摘要class:

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”这样的表达式和 returns 适当的 Operator 的子 class(在这种情况下添加):

public class OperatorCreator {

    public static Operator getInstance(String expr) {
        ...
    }
}

主要问题: 并且想通过扩展Operatorclass让别人设计自己的算子。并以多态方式使用它们的运算符。像这样:

public class Main {

    public static void main(String[] args) {
        Operator op = OperatorCreator.getInstance("1-2");
        System.out.println(op.getOperatorResult());
    }
}

我该怎么做?

编辑: 我知道可以使用反射。但如果可能的话,我宁愿不使用反射。而且我知道我可以让 Operator 的子 class 的设计者在运行时使用调用方法来注册她的新 class。但是我不想用这个方法。

谢谢!

基本上你问的是如何实现一个框架;在以下意义上:

如果其他方可以提供 classes 来实现一个运算符;要点是:你需要一个中央实例来理解哪个 class 为哪个运算符提供实现。

因此,一个解决方案是 "implementer" 必须提供一种方法,例如 "getOperator()" ... 然后 return“-”或“+”或其他.

然后您可以对 "scan" class 文件使用反射,如果它们实现了您的接口;如果是这样;您可以调用 "getOperator()" 来了解哪个 class 提供了哪个实现。稍后,您的 OperationCreator 可以使用该知识来实例化那些 classes 的对象,例如解析“1-2”所需的对象。

我更喜欢避免使用反射的方式。相反,"implementer" 应该能够调用某些方法,例如 "OperationCreator.registerOperationProvider()"。含义:首先,你告诉OperationCreator对象XYZ可以处理“-”;然后 OperationCreator 稍后可以将对“-”的调用分派给 XYZ。

如果问题的重点是如何在运行时获取实现:这就是 ServiceLoader class 的用途。然后实现者只需实现抽象 class,并放置一个像

这样的文件
 META-INF/services/your.packagename.Operator

进入他们的 META-INF 文件夹。在这个文件中,他们可以列出他们的实现:

 their.packagename.MinusOperator
 their.packagename.MultiplyOperator

当他们的代码在应用程序的 class 路径中可见时(例如,当它被打包在添加到 class 路径的 JAR 文件中时),那么您可以使用 ServiceLoader 轻松列出 Operator class 的所有实现。 JavaDoc of the ServiceLoader class 包含一个详尽的示例,说明如何完成此操作,因此我将在此处省略更多示例代码(真的很简单)。


如果问题的重点是如何使用这些实现,指的是他们可能需要的事实,例如,像getOperatorChar() 返回 -*,或更广泛地说:How to create a parser that automatically instantiates these classes, then it should be rewording a bit...