What happens when an abstract class implements an interface in Java
You can imagine an abstract
class as an unfinished class. It's like a template for actual real classes. Interface
s are mainly used to describe properties, like CanWalk
, IsCloseable
, HasAName
and so on.
There is no big difference between both concepts from the language perspective, other than that you can only extend from one class but are allowed to implement multiple interfaces.
In the end of the inheritance chain you will always have non-abstract concrete classes. Which is obvious, you can't use unfinished classes in the end, you need to finish them. That's why
Animal animal = new Animal();
does not work if Animal
is abstract
. We need to create instances of finished classes, like a Dog
who extends from Animal
.
And at that point, where you have a finished (non-abstract) class, all abstract methods need to be implemented. It doesn't matter from where those methods come from, abstract classes or interfaces, they need to be implemented.
So if you have an abstract class and implement an interface with it, you have two options for the interface methods. You either
- implement them in the abstract class or
- you leave them abstract, but then some of your more concrete children need to implement it.
Example
Let's suppose we have an interface like
public interface CanMakeNoise {
void makeNoise();
}
and the abstract class
public abstract class Animal implements CanMakeNoise {
public abstract void jump();
...
}
together with a concrete extending class
public class Dog extends Animal {
...
}
Since Dog
is not abstract, all methods need to be implemented. That is, we need implementations for jump
and makeNoise
. For the makeNoise
method we have two options, either Animal
implements it or it leaves it abstract, then Dog
needs to implement it:
// Variant 1
public abstract class Animal implements CanMakeNoise {
public abstract void jump();
@Override
public void makeNoise() {
System.out.println("hello, what's up");
}
}
or
// Variant 2
public abstract class Animal implements CanMakeNoise {
public abstract void jump();
}
public class Dog extends Animal {
@Override
public void makeNoise() {
System.out.println("Wuff wuff");
}
}
And of course Dog
needs to implement jump
:
public class Dog extends Animal {
@Override
public void jump() {
System.out.println("Boing");
}
...
}
In this case it's probably better to leave the implementation of makeNoise
up to more concrete classes since Animal
has no clue how a specific animal will sound like.
Extending the example, if you have even more concrete classes like a Chihuahua extends Dog
, you could implement the makeNoise
in Dog
since all dogs do "Wuff, wuff"
.
A method belongs to implementing class of course. I won't say that it doesn't matter where it comes from because of polymorphism. In Java you don't have multi-inheritance but you can implement multiple interfaces, so this is giving you more options about the hierarchy.