Hiding methods of superclass
Asked Answered
A

3

8

I've read the Overriding and Hiding Methods tutorial. And from that, I gathered the following:

If a subclass defines a class method with the same signature as a class method in the superclass, the method in the subclass hides the one in the superclass.

As such, I did the following:

import javax.swing.JTextArea;

public final class JWrappedLabel extends JTextArea{
    private static final long serialVersionUID = -844167470113830283L;

    public JWrappedLabel(final String text){
        super(text);
        setOpaque(false);
        setEditable(false);
        setLineWrap(true);
        setWrapStyleWord(true);
    }

    @Override
    public void append(final String s){
        throw new UnsupportedOperationException();
    }
}

What I don't like about this design is that append is still a visible method of the subclass. Instead of throwing the UnsupportedOperationException, I could have left the body empty. But both feel ugly.

That being said, is there a better approach to hiding methods of the superclass?

Anemograph answered 14/9, 2011 at 17:7 Comment(3)
just for emphasis (@Simone has the complete answer): you must not override methods of a superclass without fulfilling its contract. BTW, the sentence you quoted is about class methods while you override a instance method here.Niela
@kleopatra, I marked the answer I did because I felt that this question wasn't going to garner any more attention. I still don't feel that this question has been sufficiently answered. Maybe you could provide one of your own? You seem to be knowledgeable! :DAnemograph
i know the question it's old but i just found this so... I normally use your way to do this, one thing that i also do is to override methods as final so that the class can't be extended to enable certain features as append.Phelloderm
K
11

Use composition, if possible. This is recommended by Joshua Bloch in Effective Java, Second Edition.

Item 16: Favor composition over inheritance

For example:

import javax.swing.JTextArea;

public final class JWrappedLabel {
    private static final long serialVersionUID = -844167470113830283L;

    private final JTextArea textArea;

    public JWrappedLabel(final String text){
        textArea = new JTextArea(text);
        textArea.setOpaque(false);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
    }

    //add methods which delegate calls to the textArea
}
Kono answered 14/9, 2011 at 17:16 Comment(2)
+1, I appreciate the suggestion, although this isn't really desirable. It makes sense, but then I won't be able to add a JWrappedLabel instance directly to a container. Instead, I'll have to query the object for its text area, which I really don't want to do. But if composition is the only other alternative, I'd rather throw exceptions. Either way, it looks like the final solution is going to be rather ugly. :/Anemograph
The only thing I'd add is implement an interface that allows you to add the JWrappedLabel to a container. That will solve the problem mrkhrts has noted above.Monies
E
3

Nope that I know of.

It is a OOP problem/feature. You class still IS a JTextArea, and as such it could be used by code unaware of you subclass which would treat it as a JTextArea, expecting all of the method in JTextArea to be there and work properly.

If you need to define a new interface, you should define a new class not extending JTextArea but instead encapsulating it.

Elston answered 14/9, 2011 at 17:12 Comment(0)
L
1

Yes, use a delegate rather than extending.

Latif answered 14/9, 2011 at 17:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.