I cannot access concrete class' methods polymorphically

228 views Asked by At

I have an Interface MyInterface with two methods doSomething() and doSomethingElse().

I have an Abstract public class A that implements this interface. I Have a class C that extends class A and therefore implements the interface's methods as well. On the main method I assign the object of class C to a MyInterface reference like: MyInterface myiface = new C();

The problem is that if I add some methods in either class (abstract or concrete) I cannot call the method through the reference myiface. I have to downcast it first. Shouldn't I be able to polymorphically access the class as it is shown in the book Java SE8 for programmers of Deitel (Chapter 10 Polymorphism and Interface) ?

2

There are 2 answers

0
Mario Köhler On

Think of it like this...imagine your MyInterface is named 'Animal' and you have two classes implementing it, named 'Dog' and 'Cow'. just because they are both animals you wouldn't expect the Dog to suddenly give milk, right? In this analogy giveMilk() is a method only implemented by the Cow class.

do you get it?

1
T.J. Crowder On

Shouldn't I be able to polymorphically access the class...

You could — if the type of your variable were of type C. But it isn't, it's of type MyInterface, and that completely defines what features of the instance you have access to. Yes, the instance has more features, but code written to the interface doesn't know that.

Adding features to C has little to do with polymorphism. In this case, the polymorphism (there are a couple of different kinds of it) is that A and C could implement MyInterface's features in different ways, but your code using instances via a MyInterface reference neither knows nor cares that the instances are As or Cs; all it knows, all it should know, is that they claim to be faithful implementations of MyInterface.

Let's take a concrete example:

public void doSomethingWith(List list) {
    // ...
}

When something calls doSomethingWith, it passes in an instance that fulfills the List interface. That's all that that method knows about the instance (absent things like instanceof and getClass). The instance could be an ArrayList, a LinkedList, a Stack, etc.; but the code using it doesn't know or care about that. All it knows is that it's a List. Even if the method is passed an ArrayList, it can't use (say) ensureCapacity without first downcasting the reference (which will fail if the instance isn't an ArrayList), because not all List implementations have ensureCapacity.