Search code examples
javainheritanceabstraction

What is the best way to implement helper functions inside an abstract class in Java?


Let's assume that we have an abstract class (let's just call it X) that is inherited by a number of classes (we'll call them A and B for now). Each class that inherits from X does similar, but slightly different things, so while the implementation of each of their public methods might be slightly different, they can all use the same helper functions to avoid duplicating code. However, it makes no sense for any of these helper functions to be accessed by any class that is not a subclass of X.

Furthermore, what if there are a number of helper functions which are only meant to be used inside of classes that extend X, but need to have a slightly different implementation in each class?

Here's an example:

public abstract class X {
    public abstract void doStuff();

    int helperFunction(int a, int b) {
        return a + b;
    }
    
    abstract void secondHelperFunction(int x);
}

public class A extends X {
    @Override
    public void doStuff() {
        //do some stuff
        helperFunction(a, b);
        //so some other stuff
    }
    
    @Override
    void secondHelperFunction(int x) {
         //implementation A
    }
}

public class B extends X {
    @Override
    public void doStuff() {
        //do some different stuff
        helperFunction(b, a);
        //do other stuff
    }

    @Override
    void secondHelperFunction(int x) {
        //implementation B
    }
}

(This example is obviously very simple, I'm just trying to get my point across)

My question is, what would be the best way to do this? For example, what access modifier should be used for the helper functions? Obviously private isn't an option, since then subclasses wouldn't be able to use it. Default and protected sound like a better choice, but they still allow non-subclasses to use these functions, as long as they are in the same package as X. Would the best solution to this issue then be to enclose X and all classes that inherit from it in their own package, separate from the rest of the program? Or should one perhaps look into another form of abstraction, e.g. interfaces? (Although I cannot think of a way to deal with this using interfaces in particular)


Solution

  • A couple of options for you to consider:

    1. Use protected. You are correct that this does not prevent other classes within the same package from calling the method. But is that really a problem? The idea of a package is to gather related classes together and control the interface through which they are called. Access modifiers are a relatively coarse control mechanism that are designed primarily to help humans avoid errors when coding.

    2. Put the helper functions in a separate class and use composition rather than inheritance. You could still override methods to provide different behaviours. The downside is you will need to pass in any values required. But this isn't necessarily a bad thing as it makes the dependencies clear.