1

Consider the following class that defines and implements the Foo interface:

public class MyClass {

    public Foo getFoo() {
        return new FooImpl();
    }

    public void fooMethod(Foo foo) {
        final fooImpl = (FooImpl) foo;
        fooImpl.hiddenMethod();
    }

    public interface Foo {
        void doSomething();
    }

    private class FooImpl implements Foo {
        public void doSomething();

        void hiddenMethod() {
        }
    }
}

Outside classes will call MyClass.getFoo() to obtain a Foo object and may pass it back to fooMethod(). fooMethod() expects the FooImpl implementation of Foo and casts Foo to FooImpl so it can call package-private method hiddenMethod().

My question is, I'm not crazy about casting Foo to FooImpl. Is there another pattern I can use to do the same thing?

Thanks in advance...

Barry Fruitman
  • 12,316
  • 13
  • 72
  • 135
  • Make your `fooMethod` accept a `FooImpl`. – Sotirios Delimanolis Apr 10 '14 at 18:16
  • Why is `Foo` an `interface`? Normally, when you write an interface you expect that, at least in theory, there might be more than one class implementing it. If you're writing an interface and expect there to be just one implementation, then I have to question why you're writing it as an interface. Maybe there's a good reason. But if you explain what that reason is, maybe we can point you to a better way to organize the code. (P.S. There are reasons for doing things this way in C++ that don't apply to Java.) – ajb Apr 10 '14 at 18:22

3 Answers3

4

The problem here is that you are implicitly violating the principal of encapsulation. You have a method in your class which depends on the implementation and is therefore not part of the Foo interface. This is a violation of OO principals, this cast is only the tip of the iceberg. What if you want to design a new Foo implementation class which does not have the methods you want to call?

You should redesign your code so that you can achieve this calling only methods from the Foo interface.

phil_20686
  • 4,000
  • 21
  • 38
1

You could add a hiddenMethod method to the Foo interface

public interface Foo {
    ...   
    void hiddenMethod();
}

Since an interface is a contract for supported operations, you don't need to (shouldnt?) cast the object to access methods outside of the interface

Reimeus
  • 158,255
  • 15
  • 216
  • 276
0

You have to downcast.

Do in this way

public void fooMethod(Foo foo) {
   if(foo instanceof FooImpl){
      final FooImpl fooImpl = (FooImpl) foo;
      fooImpl.hiddenMethod();
   }
}

Super type can't be downcast without an explicit downcast. Be sure to check it before downcast using instanceof operator.


--EDIT--

Do one more thing if you want to avoid the casting. Add hiddenMethod() in Foo interface also.

public interface Foo {
    void doSomething();
    void hiddenMethod();
}
Braj
  • 46,415
  • 5
  • 60
  • 76