Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

use of interfaces  RSS feed

 
N Goldsmith
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Is there a better way to do this?

We have a generic interface:

public interface INode{
}

public interface IFlow{
...
INode getNode(int index);
}

Now a client can come along and create a specialized type of flow/node

public interface IClientNode extends INode{
somenewmethod();
}

public class ClientNode implements IClientNode{
...
}

public interface IClientFlow extends IFlow{
somenewmethod();
}

public class ClientFlow implements IClientFlow{
...
INode getNode(){
return new ClientNode();
}
}


Our client can create new client nodes, but anyone that wants to use the specialized methods in the client would have to do this:
cf = new ClientFlow();
INode node = cf.getNode();
if(node instanceof IClientNode)
((IClientNode)node).somenewmethod();

I know we can put a specialized getNode in the client (ie IClientNode getClientNode()), but we want the generic interfaces to set what all derived interfaces will do. For instance, anything that derives from IFlow, must have a getNode method. I really don't like the overhead of the solution above where we get an INode and have to figure out its class and then cast it.

Maybe interfaces aren't the best way to go or we are using them incorrectly, or this is just the way you do it in Java. I've only begun using Java, so I'm still green. Any advice?

thanks!
 
Tony Jackson
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello N,

Your email is a bit confusing; maybe you can clarify.

You say: "but we want the generic interfaces to set what all derived interfaces will do. For instance, anything that derives from IFlow, must have a getNode method."

This is already true. When you define the IFlow interface, you are mandating that any IFlow object has a getNode(int) method. Any class that implements IFlow must have a method with this exact signature. Someone else may define an Interface that extends IFlow, and that's ok. Since the interface extends IFlow, the derived Interface still has your getNode method. So any class that extends the derived Interface must have a method with your signature.

Tony
 
N Goldsmith
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Right, that is true, but because the base interface defines the getNode, all clients of the derived interfaces must cast in order to use their specialized methods:

cf = new ClientFlow();
INode node = cf.getNode();
if(node instanceof IClientNode)
((IClientNode)node).somenewmethod();

It seems too cumbersome to require the above code in order for clients to get at any specialized methods in the derived interfaces. Is this just the way you do it in Java or is there a better solution? We still want the base interface to setup the methods all derived classes must implement, but the above code seems to have alot of overhead.

thanks for the response.
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's not so much JVM overhead as typing and reading cost. The runtime cost is very low, but the design raises a small red flag. Every time you add a new type you might have to open up this code and add an "instanceof" test and that's an opportunity for error.

We try to make core code stable so you never have to change it. Much of the study of design patterns is about exactly this kinda thing. Right this moment I'm drawing a blank on an easy way to eliminate the "instanceof" here. Anybody else?
 
Tony Jackson
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi N,

OK, I understand your issue now. This is a little similar to my confusing using the Document Object Model (DOM) for navigating through XML; You may "know" that you are getting back an Element object, but the getNode() method returns a Node object (more general). Why not cast the object when you retrieve it?

Element e = (Element) myNode.getElement();

in your case it would be:

ClientFlow cf = new ClientFlow();
IClientNode icNode = (IClientNode) cf.getNode();

this seems fine to me since you KNOW that getNode ALWAYS returns an IClientNode when it is called on a ClientFlow object.

Tony
 
N Goldsmith
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks!

Yes, I think that is what makes the most sense. The client will always deal with their type, so an instanceof should never be necessary.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!