views:

164

answers:

4
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.

+3  A: 

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");
        }
}
Esko Luontola
+2  A: 

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);
    }
}
Philipp
+1  A: 

Sorry, I find the problem description far too abstract to be able to make a recommendation. You clearly have a design issue because you generally should not need to check the type of interface. I will give it a go though... First, I need to make your problem more concrete for my small brain to understand. Instead of Foos, how about Birds?

public interface Bird {
}

public class Ostrich implements Bird {
}

public interface BirdManager {
    void fly(Bird bird);
}

public class AdvancedBirdManager implements BirdManager {

    public void fly(Bird bird) {
        System.out.println("I am in the air. Yay!");
    }

    public void fly(Ostrich ostrich) {
        System.out.println("Sigh... I can't fly.");
    }
}

public class ZooSimulation {
    public ZooSimulation(BirdManager birdManager) {
        Ostrich ostrich = new Ostrich();
        birdManager.fly(ostrich);
    }
}

public static void main(String[] args) {
    AdvancedBirdManager advancedBirdManager = new AdvancedBirdManager();
    ZooSimulation zooSimulation = new ZooSimulation(advancedBirdManager);
}

Here, the Ostrich will declare "I am in the air. Yay!" which is not what we want.

OK, so, ignoring the fact that I am failing basic OO here, the problem is that the BirdManager will look for the least-specific method that matches the type that is passed in. So no matter what kind of bird I give it, it will always match fly(Bird). We can put some if checks in there, but as you add more types of birds, your design will degrade further. Here's the tough part - I have no idea if this makes sense within the context of your problem, but consider this refactoring where I move the logic from the manager into bird:

public interface Bird {
    void fly();
}

public class BasicBird implements Bird {
    public void fly() {
        System.out.println("I am in the air. Yay!");
    }
}

public class Ostrich implements Bird {
    public void fly() {
        System.out.println("Sigh... I can't fly.");
    }
}

public interface BirdManager {
    void fly(Bird bird);
}

public class AdvancedBirdManager implements BirdManager {

    public void fly(Bird bird) {
        bird.fly();
    }
}

public class ZooSimulation {
    public ZooSimulation(BirdManager birdManager) {
        Ostrich ostrich = new Ostrich();
        birdManager.fly(ostrich);
    }
}

public static void main(String[] args) {
    AdvancedBirdManager advancedBirdManager = new AdvancedBirdManager();
    ZooSimulation zooSimulation = new ZooSimulation(advancedBirdManager);
}

Our Ostrich now says the correct thing and the bird manager still treats it as just a bird. Again, bad OO (Ostriches should not have fly() methods) but it illustrates my thoughts.

SingleShot
(see my additions above). Note to self: use birds, not foo. :)Thanks, this helps a bit. I think that in my case it isn't viable to move the logic into the classes as you have done. As I explained above, the objects are Actions, and involved server side specific code. While it wouldn't get executed on the client side, I don't know if GWT would be happy have that stuff in its client side code. Hmmm not really sure though.
pj4533
A: 

As long as there are not too many implementations of Foo, I would declare an abstract method in SomeInterface for each subclass of Foo, and have an abstract class forward calls to a default method that is defined for the most general type:

public interface Foo {
}

public class SpecificFoo implements Foo {
}

public interface SomeInterface {
        void thisMethod(Foo someKindOfFoo);
        void thisMethod(SpecificFoo specificFoo);
        void thisMethod(OtherSpecificFoo otherSpecificFoo);
}

public abstract class AbstractSomeInterface {
        public void thisMethod(Foo wrongFoo) {
            throw new IllegalArgumentException("Wrong kind of Foo!");
        }

        public void thisMethod(SpecificFoo specificFoo) {
            this.thisMethod((Foo) specificFoo);
        }

        public void thisMethod(OtherSpecificFoo otherSpecificFoo) {
            this.thisMethod((Foo) specificFoo);
        }
}

public class SomeClass extends AbstractSomeInterface {
        public void thisMethod(SpecificFoo specificFoo) {
                 // calling code goes into this function
                 System.out.println("Go here please");
        }
}

public class SomeOlderClass {

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

                inInterface.thisMethod(myFoo);
        }
}
finnw