Interface freeloading on a superclass - is it good practice?

C

Chris Berg

This appears to be legal:

public interface MyInterface {
void setEnabled(boolean enabled);
}

public class MyComponent extends java.awt.Component
implements MyInterface {
// setEnable() NOT implemented, 'cause it comes with Component
}

It compiles and runs, although it appears to me there is something
conceptually wrong. Shouldn't 'implemeting an interface' mean just
that, not freeloading on some superclass?

And will it always work, on any version of VM?

Some techniques can be technically ok but still considered bad
programming practice. What about this one?


Chris
 
M

Monique Y. Mudama

This appears to be legal:

public interface MyInterface { void setEnabled(boolean enabled); }

public class MyComponent extends java.awt.Component implements
MyInterface { // setEnable() NOT implemented, 'cause it comes with
Component }

It compiles and runs, although it appears to me there is something
conceptually wrong. Shouldn't 'implemeting an interface' mean just
that, not freeloading on some superclass?

And will it always work, on any version of VM?

Some techniques can be technically ok but still considered bad
programming practice. What about this one?

It depends.

If setEnable() in Component satisfies the intention of MyInterface,
then I don't see a problem.
 
B

bugbear

Chris said:
This appears to be legal:

public interface MyInterface {
void setEnabled(boolean enabled);
}

public class MyComponent extends java.awt.Component
implements MyInterface {
// setEnable() NOT implemented, 'cause it comes with Component
}

It compiles and runs, although it appears to me there is something
conceptually wrong. Shouldn't 'implemeting an interface' mean just
that, not freeloading on some superclass?

And will it always work, on any version of VM?

Some techniques can be technically ok but still considered bad
programming practice. What about this one?

In the case of "Adapters" it's the entire purpose
of the superclass.

http://www.wdvl.com/Authoring/Scripting/Tutorial/java_adapters.html

Sadly, the "Pattern Book" uses the word Adapter to mean something
utterly different.

BugBear
 
J

Jon Martin Solaas

Chris said:
This appears to be legal:

public interface MyInterface {
void setEnabled(boolean enabled);
}

public class MyComponent extends java.awt.Component
implements MyInterface {
// setEnable() NOT implemented, 'cause it comes with Component
}

It compiles and runs, although it appears to me there is something
conceptually wrong. Shouldn't 'implemeting an interface' mean just
that, not freeloading on some superclass?

And will it always work, on any version of VM?

If not there would be something fundamentally wrong with the jvms that
(don't) run the program.
Some techniques can be technically ok but still considered bad
programming practice. What about this one?

Can you think of any other way? To me it seems you want to utilize the
interface mechanism to structure your program. Sounds like good
programming practice to me ... The only thing I'd change is the name of
MyInterface, I'd call it Enableable ;-)
 
C

Chris Berg

In the case of "Adapters" it's the entire purpose
of the superclass.
I see the point, but I think that's not completely the same situation.

The normal use of Adapter is:

class MyClass extends MouseAdapter { ...

not

class MyClass extends MouseAdapter implements MouseListener { ...

The last example is what resembles mine. It will compile, but it
claims to implement the interface without necessarily doing it.
MouseAdapter and MouseListener has exactly the same methods, which is
why 'implements MouseListener' is ambiguous, but that is not the case
in my example. So anyoune reading the code would get confused.

Well, as I said, it works tecnically, I just wondered if it was
considered good practice...

Chris
 
P

Patricia Shanahan

Jon Martin Solaas wrote:
....
Can you think of any other way? To me it seems you want to utilize the
interface mechanism to structure your program. Sounds like good
programming practice to me ... The only thing I'd change is the name of
MyInterface, I'd call it Enableable ;-)

I can think of another way, I just consider it inferior.

public class MyComponent extends java.awt.Component implements Enableable{
void setEnabled(boolean enabled){
super.setEnabled(enabled);
}
}

Of course, it leads to a lot of junk code, and brings no benefit because
an inherited setEnabled is just as much a member of MyComponent as one
declared in the class body.

Patricia
 
C

Chris Berg

Well, it's really not a purely academic discussion. Here is an excerpt
from the actual program:

public interface IToolButton{
boolean isSelected();
void setSelected(boolean selected);
void click();
void setEnabled(boolean enabled); // inherited from Component
void repaint();
void toggleSelected();
int getID();
void setActive(boolean active);
void setVisible(boolean visible);
void invalidate();
void validate();
boolean isDoubleClick();

}

An IToolButton CAN be implemented by a lightweight java.awt.Component,
but it can also be implemented by something else, for instance by
interfacing to some JavaScript code. The rest of the program treats
any implementation solely as an IToolButton (good practice!), and if I
implement it NOT using a java.awt.Component, I will have to supply all
the methods, most of which come free in Component.

Chris
 
J

jan V

Some techniques can be technically ok but still considered bad
programming practice. What about this one?

You highlight a not-so-happy facet of Java (it's hard to think of everything
when you design something as complex as a general purpose language.....).

The pragmatic solution is not to do what you highlighted. And to avoid any
accidental situations like the one highlighted, you should choose your
interface method names with care. Knowing a few thousand core API method
names helps to avoid collisions ;-)
 
J

jan V

Well, it's really not a purely academic discussion. Here is an excerpt
from the actual program:

public interface IToolButton{
boolean isSelected();

boolean isDoubleClick();

}

An IToolButton CAN be implemented by a lightweight java.awt.Component,
but it can also be implemented by something else, for instance by
interfacing to some JavaScript code. The rest of the program treats
any implementation solely as an IToolButton (good practice!), and if I
implement it NOT using a java.awt.Component, I will have to supply all
the methods, most of which come free in Component.

It does look a bit like you're trying hard to bend reality to fit some
strange "clever" scheme which may be more trouble than it's worth, in the
long run. As with many apparently-clever schemes, this one smells of
potential problems: say that Sun, in their infinite wisdom, decide that one
or more of the methods you've "hijacked" in your interface need
reimplementing, possibly with their functionality subtly changed. Suddenly
your clever interface scheme breaks... and you're desperately forced to
patch the new AWT or Swing component (by overriding the newly "misbehaving"
methods) to behave the way your interface expects a subset of AWT/Swing
component methods to behave. These patches may be impossible to write, in
which case you'll be forced to rename some of your interface methods, which
in turn will force you to implement those methods you previously believed to
come "for free" in Component, etc..

So all in all, unless my prediction of trouble ahead is flawed, I think you
need to go back to the drawing board on this one.,..
 
O

Oliver Wong

jan V said:
say that Sun, in their infinite wisdom, decide that one
or more of the methods you've "hijacked" in your interface need
reimplementing, possibly with their functionality subtly changed.

Anytime the behaviour of a publicly expose method (whether written by
Sun or anyone else) changes, then there's the possibility that someone or
something using that method will break.

That's a fundamental weakness in OOP, though as far as I know, no other
paradigm exists that can address this weakness.

- Oliver
 
O

Oliver Wong

Chris Berg said:
The normal use of Adapter is:

class MyClass extends MouseAdapter { ...

not

class MyClass extends MouseAdapter implements MouseListener { ...

The last example is what resembles mine. It will compile, but it
claims to implement the interface without necessarily doing it.
MouseAdapter and MouseListener has exactly the same methods, which is
why 'implements MouseListener' is ambiguous, but that is not the case
in my example. So anyoune reading the code would get confused.

Well, as I said, it works tecnically, I just wondered if it was
considered good practice...

Yeah, this is a weakness in Java (name collisions when implementing
interfaces) which C# has fixed (see
http://www.csharphelp.com/archives/archive171.html for an example of the
syntax C# uses to address this).

I don't like the .NET API library, so I hope Sun copies C#'s solution
into some future version of Java (Java 1.6? 1.7?)

- Oliver
 
J

jan V

say that Sun, in their infinite wisdom, decide that one
Anytime the behaviour of a publicly expose method (whether written by
Sun or anyone else) changes, then there's the possibility that someone or
something using that method will break.

Of course, and how many, many, dozens (hundreds?) of times has this happened
in the core library? The Java Bug Database is littered with regression bugs.
Which is why it's not a great idea to define interfaces containing methods
that totally overlap with already-existing methods in classes that you will
then subclass and "impose" said interface on.
 
D

Daniel Dyer

Yeah, this is a weakness in Java (name collisions when implementing
interfaces) which C# has fixed (see
http://www.csharphelp.com/archives/archive171.html for an example of the
syntax C# uses to address this).

I don't like the .NET API library, so I hope Sun copies C#'s solution
into some future version of Java (Java 1.6? 1.7?)

- Oliver

I didn't know that C# did things differently in this respect. I'm not
sure I like it, it would appear that you can change the observed behaviour
of the object just by casting. It reminds me of multiple inheritance in
C++.

In the second example, what happens if I do this:

t.MyFunction();

???

Does this result in a compile-time error because it's ambiguous or does it
prefer the I1 version because it is specified first in the extends list?

Dan.
 
J

jan V

Well, as I said, it works tecnically, I just wondered if it was
Yeah, this is a weakness in Java (name collisions when implementing
interfaces) which C# has fixed (see
http://www.csharphelp.com/archives/archive171.html for an example of the
syntax C# uses to address this).

I don't like the .NET API library, so I hope Sun copies C#'s solution
into some future version of Java (Java 1.6? 1.7?)

No, no, **NO** please !!!! Enough of this "Oh, C++ has solved that, let's
copy C++'s solution into Java".

Java used to be KISS all the way, and was a huge success because of it. With
the latest language additions, Java has become decidedly un-Java. Java
always used to be totally, utterly readable. Now with generics, more and
more people are writing utterly unreadable code (= garbage, IMO).
 
A

Andrew McDonagh

Chris said:
This appears to be legal:

public interface MyInterface {
void setEnabled(boolean enabled);
}

public class MyComponent extends java.awt.Component
implements MyInterface {
// setEnable() NOT implemented, 'cause it comes with Component
}

It compiles and runs, although it appears to me there is something
conceptually wrong. Shouldn't 'implemeting an interface' mean just
that, not freeloading on some superclass?

And will it always work, on any version of VM?

Some techniques can be technically ok but still considered bad
programming practice. What about this one?


Chris

Java Interfaces are purely a typing mechanism, which specifies that the
implementing class (be it a base/abstract/derived class) implements the
signatures of the interface. It is irrelevant which class within a
hierarchy satisfies this contract, just that it is satisfied.

This is because the Interfaces are only concerned with method
signatures, not their implementation.

The code you have posted above is very good example of one use of
interfaces. The MyComponent class is satisfying the Interface contract
simply because its base class already has a method with the same
signature.

This example is not the Adapter pattern though. That pattern would be:


public abstract class MouseAdapter implements MouseListener {

public void onMouseDown(MouseEvent e) {
}

// rest of interface methods stub implemented
}

This pattern is useful if the interface has a lot of methods signatures,
but the implementing classes do not need to do anything with them. So,
by having your own class which extends the MouseAdaptor, you don't have
to stub implement the unneeded methods yourself.

However, IMHO, this is almost (note I don't say always) an anti-pattern.
If we used the Interface Segregation Principle, then we would not need
to have so many interfaceAdaptors.

HTH

Andrew
 
A

Andrew McDonagh

Patricia said:
Jon Martin Solaas wrote:
....


I can think of another way, I just consider it inferior.

public class MyComponent extends java.awt.Component implements Enableable{
void setEnabled(boolean enabled){
super.setEnabled(enabled);
}
}

Of course, it leads to a lot of junk code, and brings no benefit because
an inherited setEnabled is just as much a member of MyComponent as one
declared in the class body.

Patricia

Though as you know, the main benefit of having an interface is the
typing aspect of it.

With having MyComponent extend Component, it can only be passed and used
as an AWT component, which means all of the other methods of Component
are available too. It also means that users of the MyComponent are now
dependent upon AWT's component.

Whereas if it also implements the 'Enableable' interface, we can pass it
around as Enableable. This gives us the benefit that we have reduced the
public interface of MyComponent to just those methods we want to. This
removes dependencies and coupling.

Without this mechanism, Dependency Inversion, Dependency injection, etc
would be difficult at best.

Andrew
 
P

Patricia Shanahan

Andrew said:
Though as you know, the main benefit of having an interface is the
typing aspect of it.

With having MyComponent extend Component, it can only be passed and used
as an AWT component, which means all of the other methods of Component
are available too. It also means that users of the MyComponent are now
dependent upon AWT's component.

Whereas if it also implements the 'Enableable' interface, we can pass it
around as Enableable. This gives us the benefit that we have reduced the
public interface of MyComponent to just those methods we want to. This
removes dependencies and coupling.

Without this mechanism, Dependency Inversion, Dependency injection, etc
would be difficult at best.

Andrew

Note that I have no problem with the use of the interface. My comment
about junk code related to my suggestion of a possible, but undesirable,
way of avoiding the use of an inherited method to satisfy the interface
requirements.

Patricia
 
A

Andrew McDonagh

Patricia said:
snipped



Note that I have no problem with the use of the interface. My comment
about junk code related to my suggestion of a possible, but undesirable,
way of avoiding the use of an inherited method to satisfy the interface
requirements.

Patricia

Sure, but for the OPs sake, I just wanted to expand upon why the
situation he has is in fact a good thing, if used correctly.
 
R

Roedy Green

It compiles and runs, although it appears to me there is something
conceptually wrong. Shouldn't 'implemeting an interface' mean just
that, not freeloading on some superclass?

Not at all. It just means your end object has the behaviours
described by the interface. How it got them is immaterial.

The terminology "implements" suggests doing some work. Perhaps if you
read "implements" as "can act as a".

In programming, laziness is a virtue.
 
R

Roedy Green

Yeah, this is a weakness in Java (name collisions when implementing
interfaces) which C# has fixed (see
http://www.csharphelp.com/archives/archive171.html for an example of the
syntax C# uses to address this).

the notion of which interface does a method belong to just does not
come up in Java. A method conforming to two different interfaces
belongs to both interfaces.

You can access the method via a class reference or either interface
reference.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top