Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have quite a bit of Java code that I'm re-working to be re-used. The problem is that there are many pieces that are project specific so there are ends up being a higher level of coupling between the application project and the code base project.

Compare to following situations where we use a class that implements the use of abstract methods to get the resources out of the child class, and one where we simply declare instance variables.

Abstract methods:

public abstract class SuperBaseClass {

    public abstract int getNumberOne();
    public abstract String getStringOne();
    public abstract String getStringTwo();

    public printStuff() {
        Log.i("IntAndTwoStrings", String.format("%i %s and %s",
                            getNumberOne(), getStringOne(), getStringTwo()));
    }

}

public class ReusedAppClass extends SuperBaseClass {

    public int getNumberOne() {
        return 1;
    }
    public String getStringOne() {
        return "String1";
    }
    public String getStringTwo() {
        return "String2";
    }

    public ReusedAppClass() {
        printStuff();
    }

}

Instance variables:

public class SuperBaseClass {

    protected int numberOne;
    protected String stringOne;
    protected String stringTwo;

    public printStuff() {
        //Possibly throw RuntimeExceptions if the app didnt set these
        Log.i("IntAndTwoStrings", String.format("%i %s and %s",
                            numberOne, stringOne, stringTwo));
    }

}

public class ReusedAppClass extends SuperBaseClass {

    public ReusedAppClass() {
        numberOne = 1;
        stringOne = "String1";
        stringTwo = "String2";
        printStuff();
    }

}

Is there a trade-off? Is the abstract method situation overkill, or is this what abstract classes were created for?

share|improve this question
add comment

4 Answers

up vote 8 down vote accepted

I think the abstract methods are the better choice. If the implementation of these properties is not something you want the sub-classes to worry about, you may even want the base class to be responsible for it i.e. use private fields in the base class with public accessors and protected mutators:

public class SuperBaseClass {

    private int numberOne;
    private String stringOne;
    private String stringTwo;

    public int getNumberOne() { return numberOne; }
    public String getStringOne() { return stringOne; }
    public String getStringTwo() { return stringTwo; }

    protected void setNumberOne(String numberOne) { this.numberOne = numberOne; }
    protected void setStringOne(String stringOne) { this.stringOne = stringOne; }
    protected void setStringTwo(String stringTwo) { this.stringTwo = stringTwo; }

    public printStuff() {
        Log.i("IntAndTwoStrings", String.format("%i %s and %s", getNumberOne(), getStringOne(), getStringTwo()));
    }
}

This kind of approach provides strong encapsulation i.e. the amount of code that can directly modify your fields is minimized.

share|improve this answer
    
Better encapsulation is a definite advantage to using abstract methods +1 –  Styler Feb 7 '12 at 15:12
add comment

Abstract class approach also forces the extending class to "initialize" the variables whereas with the protected instance variables the defaults could easily be used leading to confusion/bugs if not extended.

share|improve this answer
    
+1 for robustness –  Styler Feb 7 '12 at 15:13
add comment

IMHO a better approach is to use composition and avoid inheritance altogether if it's just for the sake of customising some fields. You say "to get the resources out of the child class", so do it:

public class MyResources() {

private int numberOne;
private String stringOne;
private String stringTwo;

public int getNumberOne() {
    return numberOne;
}

public void setNumberOne(int numberOne) {
    this.numberOne = numberOne;
}

public String getStringOne() {
    return stringOne;
}

public void setStringOne(String stringOne) {
    this.stringOne = stringOne;
}

public String getStringTwo() {
    return stringTwo;
}

public void setStringTwo(String stringTwo) {
    this.stringTwo = stringTwo;
}
}

Then instantiate MyResources objects in your classes and customise them as required. If you still need to have a hierarchy of classes you can have your resource object in the base class and inherit it in the child classes:

public abstract class SuperBaseClass {

protected MyResources resources;

public SuperBaseClass() {
    resources.setStringOne("Hello");
}

public class ReusedAppClass extends SuperBaseClass {

public ReusedAppClass () {
    super();
    resources.setStringOne("Hi");
}
}
share|improve this answer
add comment

If all those variables are properties of the base class and children uniformly depend on them then declaring them in the base is appropriate, and adding abstract get/setters/accessors would be the way to allow children to massage the data as they see fit. This is not overkill at all and OOP is designed to express these kinds of relationships.

If you find that you're raising way too much of this kind of data to the base class (or this data isn't universally common to all children) then it might be time for a bigger refactorization of the base class into a container for other, more specific base classes to help organize your logic and code. This would be a little more complex but allow for a cleaner design, and with good naming one easier to follow.

In either of my cases you must first analyze what exactly it is you expect to reuse before changing things up. Creating a reusable framework from existing code will end up in a very different place than reorganizing data and operations on that data for module reuse, for example.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.