Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I ensure that an interface implementation extends a particular class?

I have two types of editors. One is a subclass of JTextArea and one is a subclass of JTable (JTextArea and JTable are both subclasses of JComponent). I want my two classes, TextAreaEditor and TableEditor to implement the interface Editor, which just has the method public String getText().

I want the client code to simply use the Editor interface. The issue is, all of my Editors use methods of JComponent, like setEnabled(bool). Since my editor is an interface and I can't make it extend JComponent, I have to use the implementations instead of the interface when calling these methods. So I thought that instead of using an interface, I can simply make Editor a subclass of JComponent and make my classes extend that. The issue is classes like TextAreaEditor already extend some class like JTextArea, so I can't make them extend another class.

Is there any way to make sure that my Editor class is a JComponent, and that my concrete editor classes are Editors and subclasses of JComponent?

like image 495
gsingh2011 Avatar asked Dec 26 '22 20:12

gsingh2011


2 Answers

If you expose the JComponent methods you care about in a subclass of your editor interface, they would be 'retroactively' implemented by your class.

Here is some code to demonstrate the idea:

interface Editor { 
  String getText(); 
}

interface SwingEditor extends Editor { 
  void setEnabled(bool); // has to match *exactly* the signature from JComponent
}

class TableEditor extends JTable implements SwingEditor {
   // implement your getText(), and anything else you need 
   // no need to implement setEnabled, as it is provided by JTable
}

SwingEditor te = new TableEditor();
te.setEnabled(true); // will call JComponent's method

I assume you really need inheritance here, in general often composition is a better option for Swing UI code.

like image 188
ddimitrov Avatar answered Apr 09 '23 07:04

ddimitrov


Use composition over inheritacne. Most of the time inheritance is really not the right solution, and in your case, it'll save you from writing quite a bit of code.

Have your TextAreaEditor and TableEditor both have an instance of the JComponent they need. Add all the methods you need to your interface, and then delegate those calls to the JComponet.

For example:

public class TextAreaEditor implements Editor {
     private final JTextArea textArea = new JTextArea();

     public void setEnabled(bool isEnabled) {
          return textArea.setEnabled(isEnabled);
     }

     //... your own methods plus other methods from JComponent
}

You might want to get a bit more fancy and use some sort of dependency injection to instantiate the JComponent, but that's not really necessary. It could, however, solve the problem of having to have to classes if all the changes is which particular JComponent you need to inject.

Let me know if you need more clarificaiton.

like image 45
Esteban Araya Avatar answered Apr 09 '23 09:04

Esteban Araya