【问题标题】:force sub-classes to do something when they are being loaded强制子类在加载时执行某些操作
【发布时间】: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


【解决方案1】:

您可以扩展Operator 类层次结构,使其具有每种符号类型的抽象子类,例如AddOperatorSubtractOperatorMultiplyOperator。现在客户端通过选择要扩展的超类来为您提供运算符的类型。

【讨论】:

    猜你喜欢
    • 2011-09-26
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    • 2022-01-15
    • 2015-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多