views:

123

answers:

5

In my quest to correctly grasp Interface best practices, I have noticed declarations such as:

List<String> myList = new ArrayList<String>();

instead of

ArrayList<String> myList = new ArrayList<String>();

-To my understanding the reason is because it allows flexibility in case one day you do not want to implement an ArrayList but maybe another type of list.

With this logic, I set up an example:

public class InterfaceTest {

    public static void main(String[] args) {

        PetInterface p = new Cat();
        p.talk();

    }

}

interface PetInterface {                

    public void talk();

}

class Dog implements PetInterface {

    @Override
    public void talk() {
        System.out.println("Bark!");
    }

}

class Cat implements PetInterface {

    @Override
    public void talk() {
        System.out.println("Meow!");
    }

    public void batheSelf() {
        System.out.println("Cat bathing");
    }

}

My question is, I cannot access the batheSelf() method because it only exists for Cat. That leads me to believe that I should only declare from an Interface if I am only going to use methods declared in the Interface (and not extra methods from the subclass), otherwise I should declare from the Class directly (in this case Cat). Am I correct in this assumption?

+5  A: 

Yes, you are correct. You should declare as the most general type providing the methods you use.

This is the concept of polymorphism.

Borealid
+2  A: 

Yes, you are correct. By having Cat implent "PetInterface" you can use it in the example above and easily add more kinds of pets. If you really need to be Cat-specific you need to access the Cat class.

Rolf
+2  A: 

Your are correct, but you can cast from the interface to the desired pet if you need. For example:

PetInterface p = new Cat();
((Cat)p).batheSelf();

Of course if you try to cast your pet to a dog you cannot call the batheSelf() method. It would not even compile. So, to avoid problems, you could have a method like this:

public void bathe(PetInterface p){
    if (p instanceof Cat) {
        Cat c = (Cat) p;
        c.batheSelf();
    }
}

When using instanceof, you make sure you will not try to make a dog bathe himself during runtime. Which would throw an error.

Paulo Guedes
Correct answer, but leading into the wrong direction.
Axel
@Paulo - you *can* do this, but it is a bad idea. In this case for instance, it embeds the assumption that only cats can bath themselves into the `bathe` method.
Stephen C
I can see the reason for the second code snippet being a bad idea, but is the first code snippet advisable? It worked for me, but I am wondering if it is good practice?
jexx2345
+3  A: 

You can call method batheSelf from talk in Cat.

javaguy
+7  A: 
polygenelubricants
Thank you. This clarified a lot.
jexx2345