Zachary Zachary - 4 months ago 6
Java Question

Avoiding a duplicate method definition within 2+ similar child classes within a Java library

There is an issue I have been running into and I don't know the technical terms to describe it, so it has been difficult for me to search for an answer myself and I'm hoping someone might be able to shed some light what is going on here.

Let's say a library has 2 or more similar classes with somewhat similar functionality, such as JTextField and JTextArea. I would like to make an additional method available to both of these classes.

I could extend both classes and add the method to each, but the method to be added might be so similar that it could be copied and pasted into each class. This makes me think there is a better way to do this.

In this simplified example, is it possible to:
A) eliminate the near duplicate definition of "getStringValue()" between CustomJTextField and CustomJTextArea
while
B) retaining the original functionality of both JTextArea and JTextField.

CONCEPTUAL EXAMPLE:

public interface AnInterface {
public String getStringValue();
}

public class CustomJTextField implements AnInterface{
//Could Duplication of this method be avoided?
@Override
public String getStringValue(){
return this.getText();
}
}

public class CustomJTextArea implements AnInterface{
//Mirrors CustomJTextField's definition
@Override
public String getStringValue(){
return this.getText();
}
}

public class CustomJCheckbox implements AnInterface{
@Override
public String getStringValue(){
return this.isSelected() ? "Checked" : "Not Checked";
}
}

public class Main{
public static void main(String[] args) {
ArrayList<AnInterface> items = new ArrayList<AnInterface>();
items.add(new CustomJTextField());
items.add(new CustomJTextArea());
items.add(new CustomJCheckbox());

for (AnInterface item : items){
String output = item.getStringValue();
System.out.println(output);
}
}
}


My frustration has been that I can't seem to just extend JTextComponent without losing the functionality of JTextField and JTextArea, but if both are extended, it feels like unnecessary duplication. Is there an elegant way to avoid this kind of duplication?

PNS PNS
Answer

If you use Java 8, then default method implementations in interface definitions, offer a good solution.

In the above example, you can define AnInterface as

public interface AnInterface {
    public getText(); // Abstract method (re)definition

    default String getStringValue() {
        return this.getText();
    }
}

and only override the getStringValue() method for the CustomJCheckbox class.

Of course the above is of little value for methods with trivial (e.g., 1-line) implementations. It is very useful, however, for mpore complex methods.