1

I've read a number of threads explaining the differences between Interfaces and Abstract Classes; these posts in particular was very helpful: What is the difference between an interface and abstract class? and Interface vs Abstract Class (general OO); however, I couldn't find any answers that specifically addressed my question.

Context: Today in class we wrote an interface and two classes that implement the interface:

public interface Animal{ // This is in its own file
    void move();
    void makeSound();
}

class Dog implements Animal{  // The rest of these are in another file
    public void move(){
        System.out.println("Runs.");
    }
    public void makeSound(){
        System.out.println("Barks.");
    }
}

class Fish implements Animal{
    public void move(){
        System.out.println("Swims.");
    }
    public void makeSound(){
        System.out.println("Bloops.");
    }
}

public class Zookeeper{
    public static void main(String[] args){
        Animal[] zoo = new Animal[10]; // This an array of references to an interface
        for(int i = 0; i < zoo.length; i++){
            zoo[i] = (Math.round(Math.random()) == 0)?new Dog():new Fish();
        }
        for(Animal animal: zoo){
            System.out.println(animal.getClass().getName());
            animal.makeSound();
            animal.move();
        }
    }
}

I know that it is possible because it works; my question is why does it work? I get that subclasses have an ISA relationship with their superclasses, but Interfaces aren't classes at all, so does inheritance still apply to them? Do classes that implement more than one interface have an ISA relationship to those interfaces?

The question could be further abstracted to: Why can a reference variable to an Interface house Classes that implement that interface?

Community
  • 1
  • 1
Terry Chern
  • 694
  • 1
  • 8
  • 15
  • 1
    A `Fish` ISA `Animal`. An interface describes behavior, an implementing class implements it. A `Fish` object has the behavior described by its `Animal` interface. – Sotirios Delimanolis Feb 13 '14 at 22:23
  • 1
    This rule is pretty much the same for interfaces as it is for subclasses. If you have a variable `Class x`, `x` can be an object of that class (if not abstract) or any of its subclasses; and similarly if you have `Interface x`, `x` can be anything that implements the interface. And it works for array elements too. – ajb Feb 13 '14 at 22:27
  • 1
    *Why can a reference variable to an Interface house Classes that implement that interface?* Because that's how the programming language is designed. – Luiggi Mendoza Feb 13 '14 at 22:28
  • So if I had a 2nd interface that Dog implements (say Pet, that defines interactions with owners) Dog ISA Animal and Dog ISA Pet would both be true? – Terry Chern Feb 13 '14 at 22:34
  • 1
    @TerryChern Yes. "ISA" isn't anything in the language, that's just a way we talk about things. But Java does have `instanceof`, which is about the same thing; and if you have an object `obj` that is a `Dog`, then `obj instanceof Animal` and `obj instanceof Pet` would both be `true`. – ajb Feb 14 '14 at 05:48

1 Answers1

4

Your Animal[] holds Animals, right.

But of course you know that a Dog is also an Animal, hence it can be considered as such by the compiler and added to your array as an Animal.

Of course, when you go through your array, the compiler can make no further assumptions about which reference belongs to which class, so only the interface methods are available in your loop.

A nice point for polymorphism.

Edit: Maybe your question cares more about the class vs interface differences and you're wondering how can you store references to instances of the interface at all?

Well even the previous phrasing is rough. There's no interface instances, but rather instances of interface implementations. So what your Animal[] actually holds are references to instances of whatever classes you have that implement that interface (namely Dog, Fish, NyanCat or what have you).

Also notice that in the previous explanation I didn't really care about class vs interface differences. Nor does the compiler. All it cares about is correct typing, that is, you can't actually add a String to your Animal[], for example, but only the derivatives/child-types of Animal.

Point taken for strong typing.

webuster
  • 2,490
  • 18
  • 27
  • Sorry, typed that up a bit quick. Editing to correct the problems. Thanks! – Terry Chern Feb 13 '14 at 22:26
  • So any class that implements an interface automatically ISA that interface? (When I read that out loud it makes me laugh). – Terry Chern Feb 13 '14 at 22:31
  • 1
    @TerryChern yes, it is. – Luiggi Mendoza Feb 13 '14 at 22:32
  • @TerryChern I added to my answer, maybe it clears up some more fog. – webuster Feb 13 '14 at 22:40
  • @webuster Thank you for expanding on it; I was really caught up on the "differences" between the two because the professor kept emphasizing it. It's very interesting to know that they're handled the same way at the compiler level. – Terry Chern Feb 13 '14 at 22:43
  • 1
    @TerryChern: If a variable of interface type `Quackable` is non-null, the thing it identifies *IS A* "Quack"er. I don't know why some people insist that interfaces don't define "is a" relationships, when that's their whole point. Knowing that something can Quack wouldn't be useful if one couldn't use it as a "Quack"er. – supercat Feb 13 '14 at 23:40
  • @webuster: I would suggest that a `Cat[]` cannot hold hold *any* instances of `Cat`. It holds *references* which *identify* instances of `Cat` and, as a consequence, the array itself may be said to *identify* those instances, but it doesn't *hold* them. Likewise, an array of `Animal` can't hold any instances of `Animal`; rather, it can identify objects which implement the `Animal` interface. – supercat Sep 13 '14 at 18:14
  • "So what your Animal[] actually holds are references to instances of whatever classes you have that implement that interface" didn't just say that? – webuster Sep 14 '14 at 10:07
  • emphasis on "so only the interface methods are available in your loop" – FuriousFolder Sep 17 '15 at 22:22