aspose file tools*
The moose likes Java in General and the fly likes composition vs inheritance Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Soft Skills this week in the Jobs Discussion forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "composition vs inheritance" Watch "composition vs inheritance" New topic
Author

composition vs inheritance

Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4347
    
    2

i doubt this is the first thread about this, but what does it hurt to talk about it some more? i think most people will say choose composition over inheritance, but perhaps they are just parroting what others say. i have done it both ways. when i transferred to university we had to use a MVC framework. i didn't have a problem, in fact i kind of liked it. the View class didn't extend JFrame it had one. and the Controller handled the events. it seemed to make sense in that context, but i remain unconvinced. maybe it is because the projects i write are small. if i have a single class with only around 100 lines of code, why not extend JFrame? if i didn't and i wanted to set the size from main() i would have to write a method to do it. and if i only have one event, what is the point of writing another class to handle it? i admit i have had programs with so many events that actionPerformed() started to look ugly with all the else if"s. but in general i don't see what people say is "wrong" with inheritance. i would call it a feature not a bug.


SCJP
Visit my download page
Roberto Perillo
Bartender

Joined: Dec 28, 2007
Posts: 2268
    
    3

I think you are right when you say "perhaps they are just parroting what others say". I already saw many people saying to use composition rather than inheritance, but without a good reason. We only have to be careful when using inheritance because, as Kent Beck would say, inheritance is a card we can only play once.

The thing is, it is 100% correct to use inheritance if the subclass is a special type of the class being extended. If we look at the Swing framework, we'll see so much inheritance!!! Some people may have a hard time figuring when to use "is-a" and "has-a", because, after 7 years working with Java, I can tell that object orientation is not an easy thing. And for the ActionListeners, I always use one ActionLister for each button. This way, each class is able to stick to the SRP (or Single Responsibility Principle).


Cheers, Bob "John Lennon" Perillo
SCJP, SCWCD, SCJD, SCBCD - Daileon: A Tool for Enabling Domain Annotations
Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4347
    
    2

I always use one ActionLister for each button.

i am beginning to go along with that idea. if nothing else it improves readability. strange the MVC framework we used at university had one listener for everything.
object orientation is not an easy thing.

amen to that! it took me forever before i even began to understand(i was used to procedural and failed to see what the big deal was)
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8406
    
  23

Randall Twede wrote:i think most people will say choose composition over inheritance, but perhaps they are just parroting what others say. i have done it both ways.

Actually, I like the way Josh Bloch puts it: "Design and document for inheritence; or else prohibit it".

For one thing, it highlights the fact that every aspect of inheritance needs to be documented (specifically: self-use, and the effects of overriding any overridable method); and secondly, it points you towards using final classes. In fact, I make it a point now to add final to every class and method I write, because you can always remove it later on if it's too restrictive. It's almost impossible to add it later though, when you realize it should have been there all the time. Indeed, I wish Eclipse would make it an option for auto-generated methods.

The great thing about composition is that you can stick final anywhere you like.

Other than that, I agree completely with Roberto.

Winston


Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4347
    
    2

i finally heard a fairly compelling argument for not having a JFrame be a listener. i make my JFrame public and my event handling code is public too. in fact for ActionListener , actionPerformed() is declared public so i MUST make it public too. seems like a good reason to use inner classes to be the listeners.
Mohamed Sanaulla
Saloon Keeper

Joined: Sep 08, 2007
Posts: 3096
    
  33

I would see it this way: The classes should be designed keeping in mind the Single Responsibility Principle and the hierarchy should be designed such that it doesn't violate the Liskov Substitution Principle or the Open Closed principle .

We shouldn't be using inheritance just because we want to make use of a functionality of other classes- I have seen this being done and inheritance also puts a restriction on number of classes one can inherit. Its more of avoiding abuse of Inheritance.

If all my buttons/components have different behavior then I would may be go with anonymous inner classes for defining the ActionListener.


Mohamed Sanaulla | My Blog
Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4347
    
    2

i appreciate the replies and especially the links.
i changed a very simple program to use an inner class as an action listener. the experience changed my mind. for simple programs i still think it is better to just extend JFrame and implement ActionListener.
i will post both codes and you tell me which is better.
original code:

the new code. it works but i dont like it. for one thing i had to write a constructor for the inner class that was passed a reference to the outer class in order for the dialogs to work properly.
i have done similarly in other programs, but in this case it bothers me.

even worse, both classes share the one outer class member variable(the JLabel).
of course we could correct that by passing it in the constructor as well(an even worse idea IMO).

the inner class also calls methods of the outer class(not sure this such a good idea either)

so i think for this program the original code is better.
i mean, who is going to instantiate my class in one they wrote and call my actionPerformed()?
sometimes i think we worry too much.
i admit in a larger, more complicated program these things might matter.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8406
    
  23

Mohamed Sanaulla wrote:...and the hierarchy should be designed such that it doesn't violate the Liskov Substitution Principle...

Further to Mohamed's point, you might be interested in this Is a Square a Rectangle? page.

Winston
Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4347
    
    2

i'm beginning to see the light. why am i extending JFrame when i don't override any of it's methods?
i can do this:
public class ImageViewer implements ActionListener
private JFrame frame = new JFrame();

and move the method calls from main() to the constructor where they probably belong anyway.

or i could do this:
public class ImageViewer

and have the inner class. because the outer class is no longer the JFrame i won't have to write a constructor for the inner class(and pass "this" to it).
Mohamed Sanaulla
Saloon Keeper

Joined: Sep 08, 2007
Posts: 3096
    
  33

You could think in this way: ImageViewer is a JFrame or ImageViewer uses a JFrame? I think the second option sounds suitable?
I would prefer a different class for handing the actions- it increases the code clarity to a great extent. When you separate the tasks involved, it becomes easier to think- because you can now think on the basis of task you would want to finish. A concern here would be that when you have a separate class for ActionListener then there should be some way to get hold of the object on which you would want to perform some action- this again can be accomplished by composing the object within the ActionListener.

Or if the actionPerformed is simple and using a anonymous inner class doesn't degrade the code clarity, I would go with it.

I am not sure if these would make sense for a smaller codebase, but definitely will be more concerning when the codebase becomes larger.
Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4347
    
    2

i think my last idea is best. a plain old java object and a named inner class that doesn't need a written constructor now
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3649
    
  17

Take a look at this code and tell me what you think, Randall.
Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4347
    
    2

i like it. for one thing moving JFileChooser out of actionPerformed(). i have been working on it but i couldnt get the setSize() and center() and setDefault and all that to work in the constructor.
i guess that is what this is for:
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ImageViewer();
}
});
Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4347
    
    2

i like the displayImage() method also. im still having a problem in my constructor. i have to look at your code some more to figure out what i'm doing wrong
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3649
    
  17

Yep. All code dealing with Swing components should be run on the event dispatch thread. invokeLater() takes care of this.

Note also that there is a strong separation between the actions and the viewer here. I made the actions private fields, only because I think the code is a bit more readable that way (especially the constructor); they can very easily be put in their own source files as well (the file chooser would have to move with the open action though).

What I always do when I make GUIs is provide all the methods that make the GUI usable programmatically as well as through user interaction. Here, you can display an image programmatically very easily. All the listener really does is ask the user for input and then call the method. This makes it very easy to separate controllers from views.
Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4347
    
    2

agreed

i almost have it working now. i had one line in the constructor
setVisible(true);
where i forgot to say
window.setVisible(true);

yeah i am making the action listener a private variable... no wait...i made it a local variable in the constructor

got it working, but still do a lot in actionPerformed()

will look at your code some more later and maybe seperate things.

one last problem fixed. it didn't turn up until i noticed i was still extending JFrame. i had to change
window.setDefaultCloseOperation(EXIT_ON_CLOSE);
to
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

so i like this better than either of the original ones:

Roberto Perillo
Bartender

Joined: Dec 28, 2007
Posts: 2268
    
    3

Champion, how about moving the OpenListener class out of the ImageViewer class? I myself avoid inner classes as much as possible... actually, I never use them!

Also, I would keep the ImageViewer class extending JFrame. I think it makes sense, since you want it to be a special type of JFrame.
Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4347
    
    2

i am also a little leery of using inner classes. however in this case i think it is good for 3 reasons.
first, the code is not reusable. it only makes sense in this program.
second, the code doesn't do much and it will do even less if i make it more like what Stephan wrote.
third, if i make it a top level class, i might once again have to write a constructor and pass a reference to "this".

and i now don't think it actually should be a sub-class of JFrame because i don't override any methods.
Roberto Perillo
Bartender

Joined: Dec 28, 2007
Posts: 2268
    
    3

Ok, champ. I'd still prefer to have a separate class. But I guess this is just a matter of taste.

and i now don't think it actually should be a sub-class of JFrame because i don't override any methods.


Well champ, it's not because you aren't overriding a method that you shouldn't extend another class. The thing is, your ImageViewer represents a window. In other words, the ImageViewer is-a JFrame. This goes back to the things we were talking about in the beginning of this thread. Thinking of the ImageViewer as a JFrame will help you maintain it in the future.

This is just my opinion.
Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4347
    
    2

The thing is, your ImageViewer represents a window.

yes, and this bothers me a little, but i am still thinking if i don't override or overload a method of a class, i shouldn't extend it.

this has been a good learning experience for me. sometime a simple example will not hide the bigger concepts.

thanks again to all of you especially Stephan

and if you compile and run the code i hope you enjoy. i kind of like it (it is so simple).
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: composition vs inheritance