The Source for Java Technology Collaboration

Home » java.net Forums » Java Desktop Technologies » Swing & AWT

Thread: Swing best practice: inheritance vs. composition

Welcome, Guest Help
Login Login
Guest Settings Guest Settings
This question is answered.

Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 20 - Last Post: Mar 10, 2009 5:26 PM by: rturnbull Threads: [ Previous | Next ]
nbhatia

Posts: 5
Swing best practice: inheritance vs. composition
Posted: Jun 25, 2007 8:31 PM
 
  Click to reply to this thread Reply

I can see two ways to create a Swing frame:

1) Extend JFrame, keep references to child components as attributes in the subclass. The advantage here is that you can access the child components quite easily as attributes.

2) Do not extend JFrame, simply add child components using the add() method. In this case it is not easy to get a specific component later (only way I know is by component index). The advantage here is that you are not extending the already deep class hierarchy of Swing, and simply composing the needed functionality using existing Swing components.

What is the best practice in this situation? Below I have two examples showing the exact same functionality using each style of programing:

public class InheritedFrame extends JFrame {

private static final long serialVersionUID = 1L;

private final JTextField textField = new JTextField();
private final JButton button = new JButton("OK");

public InheritedFrame() {
super("Inherited Frame");
Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout());
textField.setColumns(10);
contentPane.add(textField);
contentPane.add(button);
pack();

button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(null, "Text field value = " + textField.getText());
}
});
}
}

public class ComposedFrameBuilder {

private final JFrame frame = new JFrame("Composed Frame");
private final JTextField textField = new JTextField();
private final JButton button = new JButton("OK");

public JFrame build() {
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());
textField.setColumns(10);
contentPane.add(textField);
contentPane.add(button);
frame.pack();

button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(null, "Text field value = " + textField.getText());
}
});

return frame;
}
}

ComposedFrameBuilder is intended to be used as follows:

new ComposedFrameBuilder().build().setVisible(true);

Anthony Petrov
Re: Swing best practice: inheritance vs. composition
Posted: Jun 25, 2007 11:58 PM   in response to: nbhatia
  Click to reply to this thread Reply

Hello nbhatia,

I wonder, why not combine both approaches? I mean, you can have both a
class NOT extended from JFrame that contains references to the child
components that you have added to the JFrame. Something like the
following code does:

  public class CompositedNOTInheritedFrame {
 
      private static final long serialVersionUID = 1L;
 
      private final JFrame frame = new JFrame("NOT inherited but 
composited Frame");
 
      private final JTextField textField = new JTextField();
      private final JButton button = new JButton("OK");
 
      public CompositedNOTInheritedFrame() {
          Container contentPane = frame.getContentPane();
          contentPane.setLayout(new FlowLayout());
          textField.setColumns(10);
          contentPane.add(textField);
          contentPane.add(button);
          frame.pack();
 
          button.addActionListener(new ActionListener() {
              public void actionPerformed(ActionEvent event) {
                  JOptionPane.showMessageDialog(null, "Text field value 
= " + textField.getText());
              }
          });
      }
 
      public void setVisible(boolean a) {
          frame.setVisible(a);
      }
  }


What do you think of this approach?

--
best regards,
Anthony


nbhatia

Posts: 5
Re: Swing best practice: inheritance vs. composition
Posted: Jun 26, 2007 6:05 AM   in response to: Anthony Petrov
 
  Click to reply to this thread Reply

Yep, this is also a valid variation. I guess my main question is whether or not to use inheritance. I had read somewhere that inheritance from Swing components should be avoided (i.e. use JFrame/JDialog as is - don't extend from it). While in general, I too favor composition over inheritance, I was wondering if there were any specific pros & cons for each of these programming techniques when writing Swing apps, especially when writing large complex Swing apps.

Thanks.
Naresh

Konstantin Volo...
Re: Swing best practice: inheritance vs. composition
Posted: Jun 26, 2007 5:22 AM   in response to: nbhatia
  Click to reply to this thread Reply

I suppose you don't want to start another holy war here? :)
My answer is 2, though most people still seem to chose 1.
Regretfully :)


nbhatia

Posts: 5
Re: Swing best practice: inheritance vs. composition
Posted: Jun 26, 2007 6:38 AM   in response to: Konstantin Volo...
 
  Click to reply to this thread Reply

I hear you. Very few people seem to USE Swing components as is - a good example is JGoodies samples - they use PanelBuilders to construct JPanels - without extending them. On the other hand, NetBeans Matisse goes the inheritance route. Most Swing books I have read also use inheritance quite heavily - perhaps it is more convenient!

Anyway, I don't want to start a holy war, just trying to find out from experienced Swing developers if they prefer one approah over the other. Are there any good examples of running into trouble from one of two approaches?

Thanks.
Naresh

i30817

Posts: 386
Re: Swing best practice: inheritance vs. composition
Posted: Jun 26, 2007 8:16 AM   in response to: nbhatia
Helpful
  Click to reply to this thread Reply

I've found that when creating a component that does the same as the other one plus functionalities, it is better to extend it. If it is a semantically new component, say a new textcomponent with different behavior, i generally compose.

Like this. If you're going to break the contract, don't extend it.

Anthony Petrov
Re: Swing best practice: inheritance vs. composition
Posted: Jun 27, 2007 12:13 AM   in response to: i30817
  Click to reply to this thread Reply

That seems to be the best explanation I ever heard.
1. Contract broken -> you SHOULD use composition.
2. Contract honored -> you MAY use inheritance.

--
best regards,
Anthony


Konstantin Volo...
Re: Swing best practice: inheritance vs. composition
Posted: Jun 26, 2007 8:19 AM   in response to: nbhatia
  Click to reply to this thread Reply

I don't think there's much difference in using inheritance with Swing or
with anything else. Perhaps, except for the one you mentioned: "The
advantage here is that you are not extending the already deep class
hierarchy of Swing" :), which I quite agree with.

And also except for the fact, that Swing classes serve as a very
transparent example of "When a class is trying to do too much" (it's a
quote from Fowler's book on Refactoring). I mean dozens of methods
bundled directly into a single class.

Starting with JComponent, it has quite a few "orthogonal"
responsibilities. It maintains components aggregation hierarchy,
geometrical properties, listeners stuff, painting, etc. Each
responsibility is defined by several methods. Having them all inserted
directly into JComponent, it constitutes far too great number of methods
in total.

And with each next level of inheritance, more responsibilities are added
to a class, and more dozens of methods are introduced, being thrown on
top of that same heap, which is still called "class" :) I think this
might be just an example for you, about how to run into trouble with
using inheritance.

As for books, I imagine their authors can be aimed at different goals,
than software developers are. Books usually refer to simple examples,
and also prefer shorter blocks of code. Is such cases, inheritance won't
do considerable damage, and would make code a little shorter, just as
desired.

As for complex software, I've never seen any (IMO) flexible and scalable
system, build upon frequent use of inheritance.

P.S.
There was some discussion of inheritance not log ago on this forum. You
can find it here:
http://forums.java.net/jive/thread.jspa?messageID=210526&#210526


tarbo

Posts: 425
Re: Swing best practice: inheritance vs. composition
Posted: Jun 26, 2007 1:29 PM   in response to: nbhatia
Helpful
  Click to reply to this thread Reply

I'll back i30817 in that subclasses should stick to the contract. I've had only minor problems with this, but I assume it can quickly become very bad.

Most of the functionality I need can be done by either making an "entirely" new component (by extending JComponent) or by composing one.

Advantages of making a new component are, as mentioned, that you don't drag all the API along, some of which could possibly not apply to your component anymore, and that you have good and fine control over which method does what. Basically, there is less crossfire going around.

However, to me, the main advantage to composing components is that you're using components that you know work (because they've been tested extensively) and that have been built with many scenarios in mind--typically more than any one developper could conceive.

In a nutshell, how I decide on extending or composing depends on what I need. If I will need frequent access to select functionality of the mother component without actually needing its children, then I extend--encapsulation works miracles, even in your very own project. If, however, I am simply laying out or patching together components, then I compose.

Then again, while I'm a happy Swing user, I'm not an experienced one.

swv

Posts: 242
Re: Swing best practice: inheritance vs. composition
Posted: Jun 26, 2007 1:35 PM   in response to: nbhatia
 
  Click to reply to this thread Reply

Well you are always free to keep a list of your components in whatever class you main() is in ...so that would be 2... I always do 2 because I can get the frame and anything it has access to and I can keep my own list of whatever is good for me...

If you want to track who comes and goes, and you're the only consumer of your API, then just add components through your own custom method and forward to JFrame after you're done doing whatever it is you want to do.

If you have an open API and consumers who aren't going to be well behaved or won't otherwise have access , you either override JFrame add() so it behaves as expected or you provide some kind of add method to your consumers that does as above.

I see it as a "do I have consumers?:" question...

ktm

Posts: 23
Re: Swing best practice: inheritance vs. composition
Posted: Jun 26, 2007 1:44 PM   in response to: nbhatia
 
  Click to reply to this thread Reply

A JFrame is a frame for your view. The relationship is analogous to that of painting and picture frame.

As far as getting specific components later, you need some kind of strategy for hanging your code together. I recommend my own electricbits framework:
http://systemsd.com/wordpress/?page_id=12

cupofjoe

Posts: 46
Re: Swing best practice: inheritance vs. composition
Posted: Jun 26, 2007 2:00 PM   in response to: nbhatia
 
  Click to reply to this thread Reply

Most Swing developers I know have built a light framework to handle 'best practice'.

I built TFrame https://tframe.dev.java.net/ but you should consider JSR296 if you have the option. Some very smart people are working on it and it will be part of the java runtime when 7.0 ships.

My TFrame instance is a singleton which you will need if you bind actions to the frames menu and toolbar. You will also need a handle to the frame for dialogs.

You could just as easily have your own reference and make it public static final for easy access.

Then I also used a mediator to handle messaging between the components. My components used composition and in my custom applications I make them data members of the panel. So for example, I might have a SearchPanel that looks like this:

public class SearchPanel
extends javax.swing.JPanel implements Mediatable

public static final String KEY = "AC Data Tool Search Panel";
private Search _searchAction = (Search) AppMediator.getAction(Search.KEY);

private JButton _searchButton;
private JComboBox _searchTypeComboBox;
private JTextField _searchValueTextField;

public SearchPanel()
{
AppMediator.add(this);
initComponents();
addListeners();
}

Lots of ways to solve this problem. The nice thing for me is when I use something like JPanel and I want to leverage JXPanel in SwingLabs for alpha transparency tricks I just have to change the class name to the right of the extends and recompile.

Hopefully my feedback might prove useful for you.

Kind regards,
Ed

tackline

Posts: 238
Re: Swing best practice: inheritance vs. composition
Posted: Jun 26, 2007 2:48 PM   in response to: nbhatia
Correct
  Click to reply to this thread Reply

Unnecessarily extending classes is criminal. Bad tutorial code is nothing new. GUIs are one of those things where programmers tend to think that the usual rules of good code for some reason don't apply.

Specific problems with extending JFrame include:
o You are exposing a *huge* interface. Go for small, focused interfaces.
o You can't easily swap your frame for a JApplet, JPanel or whatever.
o You can't easily switch the contents of a frame without creating a new one.
o It's easy to override a method by mistake (if you are lucky you will spot an icon in your editor). A classic example of this is adding an 'isValid' method. You need to memorise all 3,247 methods (2006 est. pop.) of JFrame.
o It's not at all obvious when you are calling a method on your class or on the library classes.
o You should probably split your class anyway. Monolithic blobs of code are not the way to go.

jwenting

Posts: 478
Re: Swing best practice: inheritance vs. composition
Posted: Jun 27, 2007 12:47 AM   in response to: tackline
 
  Click to reply to this thread Reply

> Unnecessarily extending classes is criminal. Bad
> tutorial code is nothing new. GUIs are one of those
> things where programmers tend to think that the usual
> rules of good code for some reason don't apply.
>
Mainly because they "learn" about coding GUIs by building something in say Netbeans and looking at the monstrosities it creates as being "good" code...

And with even the Swing tutorial now going the way of foregoing teaching Swing in favour of teaching Netbeans it'll only get worse.

rickcarson

Posts: 85
Re: Swing best practice: inheritance vs. composition
Posted: Jun 27, 2007 8:02 PM   in response to: tackline
 
  Click to reply to this thread Reply

I cannot believe that this answer got the correct sticker.

Firstly, Inheritance is actually a good thing.

Secondly, the choice of Inheritance vs Composition should be based on the needs of the design, not on some 'Software Religion Dogma'.

Thank you for playing. You fail the OOAD (Object Oriented Analysis and Design), please insert a procedural programming language to continue.

jwenting

Posts: 478
Re: Swing best practice: inheritance vs. composition
Posted: Jun 28, 2007 12:47 AM   in response to: rickcarson
 
  Click to reply to this thread Reply

> I cannot believe that this answer got the correct
> sticker.
>
> Firstly, Inheritance is actually a good thing.
>

Uh no. It CAN be a good thing. It can also be horribly abused which is what the post tries to convey (though maybe in wording that's a bit strong).

swv

Posts: 242
Re: Swing best practice: inheritance vs. composition
Posted: Jun 28, 2007 6:23 AM   in response to: tackline
 
  Click to reply to this thread Reply

tackline makes some valid points, but also some invalid ones in my opinion.

tackline said: You can't easily switch the contents of a frame without creating a new one

I don't see this. Frames contain Components which can be added and removed at will and the Frame refreshed.

tackline said:
It's easy to override a method by mistake (if you are lucky you will spot an icon in your editor). A classic example of this is adding an 'isValid' method. You need to memorise all 3,247 methods (2006 est. pop.) of JFrame.

Well this isn't true, either in my experience. with any modern editor, overriding is signified clearly in the editor. If you're not using a modern editor, then you have worse problems than a class with a lot of methods to remember...;)

tackline said:
It's not at all obvious when you are calling a method on your class or on the library classes

This is the same point with the same counterpoint as above. IntelliJ et. al. specifically make is easy to see what method has been added and what is library.

One fundamental deciding factor between inheritance and interfaces is answering he question - is my class an instance of is-a or plays-the-role-of?

It's an example of an is-a IF the class IS A , (in this case) JFrame, totally and wholly and it's being extended to ADD further responsibilities specializing it in some way. But it IS A JFrame and will always BE a JFrame needs all that JFrame offers and more.

It's an example of playing-the-role-of IF it's functionality wrapped in a JFrame because, hey, you need a JFrame somewhere in your program and you added functionality to the JFrame class as a way of killing two birds with one stone (class). But upon further analysis, it becomes evident that your new functionality is really orthogonal to the fact that it's embedded in a JFrame.

Another way to have a class that is-playing-the-role-of and therefore should not be realized with inheritance is to have a class which IS-A X but might become a Y later.

So an example of this would be a Person who IS-A Manager.

A Manager is-a Person, for sure, but the Person "inside" the Manager (extended by Manager) might not ALWAYS be a Manager, he might become a non-Manager...

So if you created this Person as an extension of Person, to wit, a Manager, (Manager extends Person), what happens when all this information about this Person- name address etc- is no longer a Manager? You have to transfer the information out of Manager and destroy that Manager object.

This can be messy. Not undoable, but messy.

Better to have said a Person is a Person and some People implement the manager interface.

That way there' s a clear entity, a Person that remains constant over time as the roles that Person plays come and go.

This is ONE consideration with respect to inheritance vs composition.

In general, the instinct of everyone was to shout - composition! That means that perhaps it's now received wisdom, and that' s good, because you should favor composition over inheritance as a general rule.

In the case of JFrame, even if I wanted to create a new kind of Frame that jumps and shouts twists and goes 3d suddenly, I STILL would wrap it inside an Object that USED the JFrame...if you have an outside consumer API that you're integrating with that needs a JFrame, this Object could just reach inside itself and pull out its contained JFrame instance...

cheers!

nbhatia

Posts: 5
Re: Swing best practice: inheritance vs. composition
Posted: Jun 30, 2007 7:25 AM   in response to: swv
 
  Click to reply to this thread Reply

Well said! smw, your comments were extremely helpful - it is much easier to answer the original question by going back to the fundamentals of inheritance and composition - as you have wonderfully done. Thanks for taking the time.

swv

Posts: 242
Re: Swing best practice: inheritance vs. composition
Posted: Jun 28, 2007 8:07 AM   in response to: nbhatia
 
  Click to reply to this thread Reply

Here is a good example of a problem that requires both inheritance and composition and neither could replace the other.

Pretend that you have a class that has but one behaviour you want to change. Call this class Foo and the method you want to change fooThis(); Foo is a public class in some library package It is possible to extend Foo if needs be.

When you examine Foo class, you see that fooThis() does a lot of things you want to preserve, but you would like it handle one thing better. So most of fooThis() is good, and the way it handles one thing is bad.

No when you look into the source for fooThis(), you see that the BadThing is does is actually the result of the execution of a method named barThis() which belongs to a class BarClass which implements an interface named BarInterface.

So you're going to extends BarClass and override barThis(), and be done.

The catch is BarClass is package protected. You're not EVER going to extend BarClass.

What do you do?

Well, if you extend Foo, call it MyFooExtensionm, you can rewrite fooThis() so that it does not use BarClass at all, but instead uses your new BarInterface implementation MyBetterBarClass whose method barThis() does a GoodThing.

You can see that inheritance was the way to go for Foo.. you want Foo for that it is- a Foo, it just needs to do something a little differently.

You can see that you were NOT going to be extending BarClass, so you needed to use composition instead. You could have even wrapped the original BarClass inside your BetterBarClass and deferred to it for all method invocations except barThis(), that is, you could have used delegation.

cheers!

darshan9987

Posts: 1
Re: Swing best practice: inheritance vs. composition
Posted: Mar 10, 2009 6:13 AM   in response to: nbhatia
 
  Click to reply to this thread Reply

Using JTabbedPane in one class how can I access the object of JTabbedPane in other class. The other class extends that main class. I tried using the name with directly but its returning null.

Message was edited by: darshan9987

rturnbull

Posts: 460
Re: Swing best practice: inheritance vs. composition
Posted: Mar 10, 2009 5:26 PM   in response to: darshan9987
 
  Click to reply to this thread Reply

> Using JTabbedPane in one class how can I access the
> object of JTabbedPane in other class. The other class
> extends that main class. I tried using the name with
> directly but its returning null.
>
> Message was edited by: darshan9987

I can see two ways, there are probably others.

In your 'one' class, have a method public JTabbedPane getTabbedPane(); and call it
from the 'other' class

or, create the JTabbedPane in the 'other' class and pass it to the constructor
of the 'one' class




 XML java.net RSS