The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Java Interface Design Question

I have an interface X. I have some logic which fires off by passing it an implementation of X. I have several implementations which I use when required.

The problem is that when I want to add a new method for a particular implementation (which is specfic to that implementation only), I must add it to the interface (so my logic can see it). But then all the other implementations of interface X needed to be updated (with empty curly braces, because they don't need it).

What is the best way to go re-engineer this so that other implementations are not hurt?
Iterator
Monday, December 05, 2005
 
 
Change it to an abstract class and provide empty method as the default implementation.
blablabla
Monday, December 05, 2005
 
 
This is not the way I would use Interfaces.
Sgt.Sausage
Monday, December 05, 2005
 
 
If a class is using X, it should be generic enough that it only deals with X as defined in the interface. So it shouldn't be calling methods that are only relevant to one implementation of X.

You may need to change your interface so it's a little more abstract (in the English sense, not in the Java sense). The methods that only exist in one implementation of X should be private or protected, so they can only be called from within X.

On the other hand, if you really need to, you could always check which class you're actually using:
if (myX instanceof XSub1) {
  XSub1 myXSub1 = (XSub1) myX;
  myXSub1->myMethod();
}
JW
Monday, December 05, 2005
 
 
Hmm never tried this, but...

If your interface is X1, you can make a new interface called X2 that extends X1.

The old code calls the old interface, new code calls the new interface, and any object that is X1 compatible should take an X2 type object, because of inheritance.

Take with a grain of salt, I have never extended an interface before.  I do implementations that take class Object sometimes though, so I know the second part will work.
flash91
Monday, December 05, 2005
 
 
Use an abstract class instead and provide a default implementation.
son of parnas
Monday, December 05, 2005
 
 
If there's a method on your interface that doesn't make sense on your implementation class(es), you've got broken abstractions, time to refactor.
Matt.
Monday, December 05, 2005
 
 
You need to cast. You can either group the new functionality in another interface, and test if the Concrete class also implements that interface, then cast it.
Or just check if the object in question is actually the class you care about, then cast it to that, and make the call.

isInstance
SR
Monday, December 05, 2005
 
 
Ho do you rip off a cheap calls website in a hurry? If your name is Joel then it's easy

Answer,

screenscrape the prices of www.loiol.co.uk or www.cheapestinternationalcalls.com
Peter Cunningham Send private email
Monday, December 05, 2005
 
 
Alternativly, you could use sub-interfaces and Casting and/or 'instanceof'
Scylla
Monday, December 05, 2005
 
 
an abstract class may save you some work, but the problem sounds like your Interface isn't very well-defined.  It sounds like it's just a bunch of random functions, and it's not particularly important if an instance actually implements any one of them.  I would rethink this and redesign the Interface so that you don't have to add new methods - that a new instance can do all it needs to just by implementing the existing methods.
With a more concrete description of the problem, I could maybe be more specific.
a unique name lets you know it's me Send private email
Monday, December 05, 2005
 
 
"What is the best way to go re-engineer this so that other implementations are not hurt?"
It sounds like you cannot. I agree with unique, your interface appears to be badly defined. Are you sure that it is a OO design, or is it a design using OO concepts?

More than a few projects I've seen in OO languages turn out not to have a (macro) OO concept. Is it possible you are working with this interface out of a desire to make things more generic? Sometimes you can't do that. Or shouldn't.

But whatever you do, don't do a if test with instanceof. ;)
Dave
Tuesday, December 06, 2005
 
 
Hey Son of Parnas,

Could you clarify your answer? 

I don't see that is solves the poster's question (I am probably just dense at the moment)
flash91
Tuesday, December 06, 2005
 
 
> (I am probably just dense at the moment)

Or I am.

An abstract class has methods that can be overriden but don't need to be. An interface requires all methods to be implemented.

So in this case you can add a method and all the classes that don't care about don't need to do anything with it. If a class does care then override it.
son of parnas
Tuesday, December 06, 2005
 
 
Using an abstract class won't work, because by implementing an Abstract class AND adding new methods (to an implementing class) will mean that any logic expecting an implementation of the abstract class will only see the methods (both abstract and non-abstract) already defined in the Abstract Class. If I write an implementation and then add a new method, the logic will not see it as it is not expecting it.

e.g.

abstract class AbstractA
{

    public void foo()
    {
        System.out.println("foo()!");
    }
    
    public void abstract bar();
}

class DefaultImpl extends AbstractA
{

    public void bar()
    {
        System.out.println("bar()!");
    }
    
    public void MyNewMethod()
    {
        System.out.println("Custom stuff");
    }

}

class Test
{

    public test(AbstractA a)
    {
        //cannot access "MyNewMethod()" from "a".
    }
}
Iterator
Tuesday, December 06, 2005
 
 
Son of Parnas:

I agree that your solution would be less work than the current situation (adding code in 2 places instead of n), but I really think the design flaw is more subtle than which polymorphism mechanism is being employed.
a unique name lets you know it's me Send private email
Tuesday, December 06, 2005
 
 
If Interface X is what your logic expects, how does the logic know when a particular implementation has the "extra" methods that you want to add?
AC the AC Send private email
Tuesday, December 06, 2005
 
 
As anonymous said, if you change your interface every time you make a new implementation it's that your interface isn't well designed.
Using an abstract class instead of an interface is not a good idea since it prevents any class that wants to implements a behavior from using inheritance.

On the other hand you might create an interface and an abstract class which implements the interface providing a "generic implementation". However if it's only to avoid empty brace, it's not very useful. A good ide can generate empty braces for all the methods of an interface in only one click.

What you might do is break the interface into multiple interfaces so your classes can implement only some functionalities. The problem is then that you have to know if an object supports such or such interface which might be a pain in the ass.

Another think you could is having a basic interface and other interfaces extending that basic interface to add other operations. That avoids you to touch your basic interface and therefore all the classes implementing such an interface. But be careful not to spawn a maze of interfaces.

One last think i am thinking about is UnsupportedOperationException.  If you have an interface where it's not mandatory for some methods to be implemented then you could specify in the interface that it is not required for implementations to support those methods by adding a "throws UnsupportedOperationException".
The Collection class in the standard library use that mechanism : http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collection.html .
Monkeyget Send private email
Tuesday, December 06, 2005
 
 
Another option is to put the implementation specific stuff into a separate interface. Then the stuff that doesn't care just doesn't implement that interface.

It's easy enough to check at runtime if a class supports a particular interface or not and fall back if it doesn't.
Chris Tavares Send private email
Tuesday, December 06, 2005
 
 
==>So in this case you can add a method and all the classes that don't care about don't need to do anything with it. If a class does care then override it.

I'm still not sure how that solves the OP's issue. He'll want to be passing around a common base class (like he's currently passing around an interface) but that common base won't implement the extra functions of each special sub class. How does this help?
Sgt.Sausage
Wednesday, December 07, 2005
 
 
Dont follow inheritance heirachy here. introduce Decorator Pattern.. and provide loosely couled system.
Sadhsivam Jayabalaganesan
Sunday, December 25, 2005
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz