Skip to main content

Swing in a better world: java interfaces

Posted by alexfromsun on March 11, 2011 at 2:12 AM PST

We have all read the "Effective Java" book and know that we should prefer interfaces over abstract classes.
This is a known and respected pattern which should be used wherever possible.

However the years in the JDK team tauhgt me not to blindly trust
to good practices from the world of application programming.

A distinctive feature of the JDK is backward compatibility.
All programms written in public JDK API must compile and run
with every next JDK versions. It makes it really different.

Comptibility is good for Java programmers but not so good for JDK developers,
java interfaces is a part of a problem.

If you want to add an interface to the JDK API you have to be sure
that you know in advance all the methods that are to be included there.
You cannot make any mistakes because it will be impossible to add a new method
to an interface without breaking the user's code.

In every JDK release we add new methods to some of the existing classes.
Let's have a look what happens when it turned out that we need to expand an interface.

The LayoutManager interface is widely used across Swing/AWT toolkit.
This interface contains 5 methods and that was enough at the beginning.
Later on it was discovered that a complex layout needs more methods there,
but it was decided to intrdoduce a new interface,
because nobody wants to implement too many empty methods for a simple layout.

So here comes the LayoutManager2 interface
and now the layout related methods from java.awt.Container look like this:

public float getAlignmentX() {
        float xAlign;
        if (layoutMgr instanceof LayoutManager2) {
            synchronized (getTreeLock()) {
                LayoutManager2 lm = (LayoutManager2) layoutMgr;
                xAlign = lm.getLayoutAlignmentX(this);
            }
        } else {
            xAlign = super.getAlignmentX();
        }
        return xAlign;
    }

 However the layout setter and getter still work with the old LayoutManger type: 

public void setLayout(LayoutManager mgr) {
        layoutMgr = mgr;
        invalidateIfValid();
    }

so you have to read the spec to know that the new LayoutManager2 exists.

If it happens that more methods should be added in a next release,
the LayoutManager3 will appear, adding more mess to the Swing API.

So now you can see why I don't like java interfaces as much as I should do.

 If I created Java...

Discussing the features of a programming language is very popular among programmers,
everybody knows how to make it in a right way, here is my try:

The interfaces in java are too restrictive and I wonder if they could be implemented more friendly for programmers.
I am dreaming about Java that allows implementing an interface without being made to implement every single method of it.

Look at the KeyAdapter class, we have it only because it is too inconvenient to implement every 3 methods
when you need only one of them. I am sure that in a perfect java there is no need in classes
like MouseAdapter, HierarchyBoundsAdapter and so on.

You don't want to type empty methods for a KeyListener?
You should use KeyAdapter.

don't want to type empty methods for a MouseListener?
Then you should use MouseAdapter.

But what if I want my class to implement KeyListener *and* MouseListener and I don't need most of the methods from them?
The only solution is to manually generate the empty stubs (thanks to my IDE which can do it automatically)

In the java of my dreams the compiler can generate empty stubs for a method from an interface your class is implementing,
so you can override only those methods that you really need.

The "empty" methods from a super interface have empty bodies and return null for reference types and zero for numbers.

Sometime it is desirable to remind a developer that a method just needs to be implemented
and abstract methods in Java classes ensure it. Currently all methods in an interface are considered abstract
no matter if they have the "abstract" keyword in their signature or not.

I think it should be more meaningful support of this keyword for java interfaces,
only methods with the "abstract" keyword must be implemented
when compiler takes care of all the rest.

With this proposal the LayoutManager interface would be implemented like this:

interface LayoutManager {

    // methods that are currently in java.awt.LayoutManager
    // the user must implement them (note the abstract keyword)
    abstract void addLayoutComponent(String name, Component comp);
    abstract void removeLayoutComponent(Component comp);
    abstract Dimension preferredLayoutSize(Container parent);
    abstract Dimension minimumLayoutSize(Container parent);
    abstract void layoutContainer(Container parent);

    // optional methods from java.awt.LayoutManager2
    // they don't have to be implemented
    void addLayoutComponent(Component comp, Object constraints);
    Dimension maximumLayoutSize(Container target);
    float getLayoutAlignmentX(Container target);
    float getLayoutAlignmentY(Container target);
    void invalidateLayout(Container target);
}

 
This was an entry from the Swing in a better world series

Thanks and see you soon
alexp 

Related Topics >>

Comments

Swing in a better world: java

You'd need to recompile for a new interface version with this proposal.
And I'd rather see the generated methods throw an UnsupportedOperationException instead of just returning null or similar.
There's merit to your suggestion though, it's definitely a problem and I'm sure it's one that is resolvable (I haven't looked at defender methods yet but I shall do so now)!

Swing in a better world: java

[quote=rich.midwinter]

 You'd need to recompile for a new interface version with this proposal.

[/quote]
Actually if this feature had been implemented from the beginning, there would be no need to recompile,
just like you don't have to recompile your code when a new method is added to a JDK class.

Swing in a better world: java

Scala solved that (I think) in a rather elegant way (also solving multiple inheritence) with traits. Kind of interface allowing implementation of the methods. And fields...

Do I hear mixin?

Do I hear mixin?

Swing in a better world: java

hey, good to know the swing world is still moving. i'm still hoping someone in the swing dev team finishes the nimbus project. jasper pott's promise that it is completely configured by uidefaults is not holding completely -- trying to get a decent dark looks seemed impossible in my attempt. the guys at jyloo did such a great job with synthetica blackeye theme. i wish someone could make a nimbus settings that comes close to this, and i think it would be possible with some tweeking, after all the blackeye theme doesn't look that much different from nimbus other than the color scheme. a dark lnf would be phantastic for professional apps in the creative sector.
regarding your actual post :) i was thinking that the java of your dreams might be reality already, and is called scala. its traits pretty much allow you to do exactly what you are describing here.

Swing in a better world: java

Jonathan Giles just let me know that there is a similar proposal called Defender Methods
it is nice to know that I am not alone :-)

Swing in a better world: java

> Jonathan Giles just let me know that there is a similar proposal called Defender Methods
> it is nice to know that I am not alone :-)

Defender methods are planned to be introduced in jd8 under project lambda [1] (JSR 335),
the original proposal was done by Neal Gafter [2] and Peter Ahé [3].

Rémi
[1] http://openjdk.java.net/projects/lambda/
[2] http://gafter.blogspot.com/2007/11/closures-prototype-update-and-extensi...
[3] http://digital-sushi.org/entry/declaration-site-extension-methods/