6

I usually prefer to follow "composition over inheritance" rule, until I start stepping in the world of Java GUI.

In my experience, for adding custom requirements in a GUI components, for example, add custom function in a JButton, usually create a class extends from JButton like this:

public class CustomButton extends JButton{
    public void customMethod(){
    }
}

I think it is obviously violating "composition over inheritance" rule, so I try achieving this by composition instead of inheritance, but the problem occurs: JButton has walls of methods, if I use composition, walls of method mapping is required in my CustomButton class:

public class CustomButton{
    protected JButton button;
    public void customMethod(){
    }

    public void add(PopupMenu popup){
        button.add(popup);
    }

    public void addActionListener(ActionListener l){
        button.addActionListener(l);
    }

    .
    .
    .
}

which may require a horrible list of methods to map to JButton.

Also there is one more problem: I don't know how to deal with built-in methods that needs JButton as parameters if my CustomButton is not the subclass of JButton.

So my question is, if the original class has too much methods, is it reasonable to use inheritance instead of composition?

  • 9
    Composition over inheritance has nothing to do with the number of methods a class contains. – Robert Harvey Jul 22 '16 at 2:40
  • 16
    Composition over inheritance is really just a way of making sure people actually think about "is my X a Y" as opposed to "would it be easy to treat X as a Y". In this case, your CustomButton really is a JButton, and I see no reason to favor composition here. Blindly following dogma is never a good choice. – Dannnno Jul 22 '16 at 3:21
  • 6
    Please, please for the love of every single programmer out there and for the profession as a whole, don't use blanket statements as rules. This is a case for inheritance, not composition. – T. Sar Jul 22 '16 at 11:12
  • 1
    I once read in stackoverflow that the only real evil on software development are dogmas. This is a good example of it. – eddieferetro Jun 5 '17 at 8:59
6

What composition over inheritance really has to say here is that it would have been nice if JButton has been designed with composition polymorphism so your CutomButton method could have been passed into it. It wasn't.

If the client needs access to everything JButton provides (dubious) you now have to create a bunch of boilerplate delegation methods if you want to do composition the other way around. There are automatic refactorings that can do dumb work like that for you but it's still yucky for maintenance. Who wants to look at that? Bleh.

So you do inheritance. What does that hurt? Well the yo yo problem isn't fun. You avoid that by not creating multiple levels of inheritance. Problem with that is now you think "ok just one won't hurt". And so does the next guy. And the next.

You can stop that with a final on the class but that's kinda an F.U. to the next guy. You could do for the next guy what you wish the JButton guy had done for you. Let them pass you something that implements a CustomInterface with a customMethod() that you'll call. The fancy name for this is object adapter pattern.

enter image description here

Now you're doing both inheritance and composition but at least the madness can come to an end.

  • 1
    Spot on. The only time I find I need to use inheritance is when using badly designed 3rd party classes that force inheritance on me. In such situations, I use it as trying to work around inheritance in such cases makes the code far more complex than it needs to be. – David Arno Jul 22 '16 at 8:05
16

If you honestly, truly need a component as general as a JButton, then you should just use inheritance. "Favor composition over inheritance" doesn't mean "never use inheritance." However, people made that buzzword phrase because 95% of the time when beginners think they need inheritance, they don't.

95% of the time, you don't actually need a component as general as a JButton. You need something a whole lot more specific. For example, here is the entire public interface for a custom button on a calculator app I wrote in Java a while ago:

public interface Button
{
    public void setOperation(Operation operation);
    public Operation getOperation();
    public void setEnabled(boolean enabled);
}

All the setup of the composed objects was done in the constructors, including event handlers that call the currently set operation's primary function when clicked. Looking at this interface, you'd have no idea it was implemented by a Swing GUI, which is a good thing, because I want to reuse most of my core code to make an Android version. My interface is semantic. It's coupled to my application's needs, not a random GUI library's needs.

Learn to write custom GUI components with interfaces that look more like mine instead of your nearly exact copy versions, and you'll begin seeing the benefits of composition over inheritance there as well.

2

The premise of the question seems to be wrong: by using composition, you create something that has a button, but is not a button itself. Composition is not a direct replacement for inheritance.

JButton is a view. Your class is either another view that has the button as a part of it or it is a controller, observing the button. Either way: it's not a button. And nobody would expect to be able to call button methods on it.

Delegating methods to a property is only necessary if you have to fulfill a contract, like in the decorator pattern for example. If you need access to the button, expose it via a getter method, not via partial method delegation.

0

You could implement delegate methods that you will use most often, for all the others just ensure there is a way for a client to obtain JButton:

public class CustomButton {
    protected JButton button;

    public void customMethod() {
    }

    public void add(PopupMenu popup) {
        button.add(popup);
    }

    public void addActionListener(ActionListener l) {
        button.addActionListener(l);
    }

    public JButton getButton() {
        return button;
    }
}

Then, for example to disable the button:

customButton.getButton().setEnabled(false);
  • Demeter disapproves this. – eddieferetro Jun 5 '17 at 8:55
0

In your case you are not overriding any of JButton methods you are trying to set some properties to JButton using your custom method so there is no need for using inheritance. You can use Builder Design Patter.
For example

public class CustomButtonBuilder {

      private JButton button;

      public CustomButtonBuilder(JButton button) {
             this.button = button;
      }

      // the build method is your same customMethod()
      public void build() {
      // here goes the custom setting for your button.
      }
}

In the above example JButton is created and required listener etc. are set using setter methods. Then it is passed to the CustomButtonBuilder where your custom functionality will be added to the JButton Object.

In this way you can choose Composition over Inheritance without writing so many methods.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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