-1

I have an interface like given below. Can I restrict all the classes which implements this interface from calling getValue for a QueryEngine which it doesn't have implementation of. The goal is to avoid the spillover of this logic to implemented classes (as there are many abstract classes which implements this interface).

public interface Node {

    <T> T getValue(QueryEngine engine, Class<T> context);

}

Right now in the implemented class, same function looks like this

public <T> T  getValue(QueryEngine engine, Class<T> context) {
        if (engine == QueryEngine.VALUE1) {
            return getValue1CustomFunction(engine, context);
        }
        return getValue1CustomFunction(engine, context); //There are no other implementations right now
    }

public <T> T getValue1CustomFunction(QueryEngine engine, Class<T> Context) {
        final String expression = String.format(Value1_PATTERN, arguments.get(0).getValue(engine, String.class));

        return queryBuilder(context, expression);
    }

Alternatively any suggestions for a generic implementation with some platform-specific pluggable overrides is also welcome (as there is only one implementation)

KVM
  • 125
  • 14
  • I don't understand why the case where `engine == QueryEngine.VALUE1` and the case where it is something else both do the same thing. Shouldn't the second one be a runtime error? – tgdavies Sep 23 '21 at 00:13
  • right now I have implementation for only one query engine, that's why both cases are doing the same thing. Can you please explain how will the second one be a runtime error ? – KVM Sep 23 '21 at 00:16
  • Does `getValue1CustomFunction` know what to do if you pass it a `QueryEngine` which isn't `VALUE1`? – tgdavies Sep 23 '21 at 00:19
  • Added that additional function to the question. It is a recursive call to the same function in any of the implmented classes of Node interface passing the same engine as parameter. All implemented classes have similar repeated pattern where only one engine logic is present. – KVM Sep 23 '21 at 00:29
  • I think what you are looking for is Template Method design pattern. Make `getValue` method private. Write a wrapper `checkAndCallGetValue` as default method which will do the checking and conditionally call `getValue` . It's better to make `Node` an abstract class. – the Hutt Sep 23 '21 at 02:13

1 Answers1

1

It is impossible what you want.

Instead you can create some root AbstactNode abstract class with this common logic. And mark method getValue as final. And seems like you want to create two functions (may be abstract functions) like getValueByQueryEngine and getValueWithoutQueryEngine.

Smth like:

public abstract class Node {
    public final <T> T getValue(QueryEngine engine, Class<T> context) {
        if (engine == QueryEngine.VALUE1) {
            return getValueByQueryEngine(engine, context);
        }
        return getValueWithoutQueryEngine(engine, context);
    }

    protected abstract <T> T getValueByQueryEngine(QueryEngine engine, Class<T> context);
    protected abstract <T> T getValueWithoutQueryEngine(QueryEngine engine, Class<T> context);
}

May be useful: Why is "final" not allowed in Java 8 interface methods?

Also in this abstract class you may want to use one of collections like:

  • Set<QueryEngine> queryEngineSupportingGetValue;
  • Map<QueryEngine, BiFunction> getValueOfQueryEngineFunctions;
Timur Efimov
  • 358
  • 2
  • 10