简体   繁体   中英

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

I want to have an abstract class like this:

public abstract Operator {

    public int[] operands;

    public Operator(int[] operands) {
        this.operands = operands;
    }

    public abstract int getOperatorResult();
}

And some operators to extend from it like:

public class Add extends Operator {

    public Add(int[] operands) {
        super(operands);
    }

    public int getOperatorResult() {
        return operands[0] + operands[1];
    }
}

And an OperatorCreator which gets an expression like "1+1" and returns the appropriate Operator's sub-class(in this case Add):

public class OperatorCreator {

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

The main problem: And I want to let others to design their own operators by extending Operator class. And use their operators polymorphically. something like this:

public class Main {

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

How can I do this?

Edit: I know it is possible using reflection. But I'd rather not to use reflection if it is possible. And I know I can let the designer of the Operator's sub-class register her new class using invoking a method at runtime. But I don't want to use this method.

Thanks!

Basically you are asking how to implement a framework; in the sense of:

if other parties can provide classes that implement an operator; the main point is: you need a central instance that understands which class provides the implementation for which operator.

So, one solution would be that an "implementer" has to provide a method like "getOperator()" ... which would then return "-", or "+" or whatever.

You could then use reflection to "scan" class files if they implement an interface of yours; and if so; you can call "getOperator()" to understand which class provides which implementation. Later on, your OperationCreator can use that knowledge to instantiate objects of those classes that are required to resolve "1-2" for example.

I would prefer a way that avoids using reflection. Instead, an "implementer" should be able to call some method like "OperationCreator.registerOperationProvider()". Meaning: first, you tell the OperationCreator that object XYZ can handle "-"; then the OperationCreator can dispatch calls for "-" to XYZ later on.

If the main point of the question is how to obtain the implementations at runtime: This is what the ServiceLoader class is for. Implementors then just have to implement the abstract class, and place a file like

 META-INF/services/your.packagename.Operator

into their META-INF folder. In this file, they can list their implementations:

 their.packagename.MinusOperator
 their.packagename.MultiplyOperator

When their code is visible in the classpath of the application (eg when it is packaged in a JAR file that is added to the classpath), then you can use the ServiceLoader to easily list all implementations of the Operator class. The JavaDoc of the ServiceLoader class contains an elaborate example showing how this can be done, so I'll omit further example code here (it's really simple).


If the main point of the question was how to use these implementations, referring to the fact that they may need, for example, a method like getOperatorChar() returning - or * , or more broadly: How to create a parser that automatically instantiates these classes, then it should be reworded a bit...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM