Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use java interfaces with multiple implementing classes

public interface Foo {
}

public class SpecificFoo implements Foo {
}

public interface SomeInterface {
    void thisMethod(Foo someKindOfFoo);
}

public class SomeClass implements SomeInterface {

    public void thisMethod(Foo someKindOfFoo) {
        // calling code goes into this function
         System.out.println("Dont go here please");
    }

    public void thisMethod(SpecificFoo specificFoo) {
        // not into this function
         System.out.println("Go here please");
    }
}

public class SomeOlderClass {

    public SomeOlderClass( SomeInterface inInterface ) {
        SpecificFoo myFoo = new SpecificFoo();

        inInterface.thisMethod(myFoo);
    }
}

calling code:

SomeClass myClass = new SomeClass();
SomeOlderClass olderClass = new SomeOlderClass(myClass);

I have an interface (SomeInterface) that several classes call into (such as SomeOlderClass). I have a class that implements the interface, but I want to do type safe operations on the specific implementations that are passed into the generic interface.

As shown in the above code, I really want to able to make another method that matches the specific type passed in to the interface. This doesn't work. I assume it is because the calling code only knows about the interface, and not the implementation with the more specific methods (even though SpecificFoo implements Foo)

So how can I do this in the most elegant way? I can get the code working by adding an if statement in the class implementing the interface (SomeClass):

public void thisMethod(Foo someKindOfFoo) {
    // calling code goes into this function
    if ( someKindOfFoo.getClass().equals(SpecificFoo.class) )
        thisMethod(SpecificFoo.class.cast(someKindOfFoo));
    else
        System.out.println("Dont go here please");
}

However, this is not elegant, as I have to add if statements everytime I add a new kind of Foo. And I might forget to do so.

The other option is to add SpecificFoo to the SomeInterface, and let the compiler sort out reminding me that I need implementations in SomeClass. The problem with this is that I end up adding quite a bit of boiler plate code. (If someone else implements the interface, they have to implement the new method, as well as any tests)

It seems that there should be another option I am missing, given that Foo and SpecificFoo are related. Ideas?

MORE INFO:

Well I actually worked for a while to try and simplify the question. As I add more details the complexity goes up by quite a bit. But whatever... I think I can explain it.

Basically, I am write a GWT web apps RPC servlet using the command pattern as explained by Ray Ryan in his talk

There are several implementations of it on google code, but many of them suffer this inherit problem. I thought it was a bug in the GWT-RPC code bugreport HOWEVER, as I was implementing further I noticed a similar problem happening purely on the client side, and while in hosted mode. (ie all java, no gwt javascript madness).

So I abstracted the basic ideas to a raw java command line case, and saw the same issue, as described above.

If you follow along with what Ray Ryan discusses, Foo is an Action, SpecificFoo is a specific action I want to call. SomeInterface is the client side RPC service and SomeClass is the server side RPC class. SomeOlderClass is a kind of rpc service that would know about cacheing and whatnot.

Obvious, right? Well as I said, I think all the GWT RPC nonsense just muddies up the waters on the base issue, which is why I tried to simplify it as best I could.

like image 658
pj4533 Avatar asked Dec 02 '25 19:12

pj4533


2 Answers

If you need to find out the actual type of an object at runtime, then the design is most probably wrong. That violates at least the Open Closed Principle and Dependency Inversion Principle.

(Because Java does not have multiple dispatch, the thisMethod(Foo)will be called instead of thisMethod(SpecificFoo). Double dispatch could be used to get around the language's limitations, but there might still be some design problem lurking there...)

Please give more information on what you are trying to accomplish. Right now the question does not provide enough information to come up with a right design.

A generic solution is that since the action depends on the runtime type of Foo, that method should be part of Foo so that its implementation can vary depending on Foo's type. So your example would be changed to something like below (possibly adding SomeInterface or other parameters to thisMethod()).

public interface Foo {
    void thisMethod();
}

public class SpecificFoo implements Foo {
        public void thisMethod() {
                 System.out.println("Go here please");
        }
}
like image 111
Esko Luontola Avatar answered Dec 04 '25 09:12

Esko Luontola


Try using double dispatch: Add a method to the Foo interface that is called by SomeClass#thisMethod. Then place the code in the implementation of this method.

public interface Foo {
  public void thatMethod(SomeClass a);
  public void thatMethod(SomeOlderClass a);
}

public class SomeClass implements SomeInterface {
    public void thisMethod(Foo someKindOfFoo) {
        someKindOfFoo.thatMethod(this);
    }
}
like image 45
Philipp Avatar answered Dec 04 '25 10:12

Philipp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!