Why do we need abstract methods?
One of the most obvious uses of abstract methods is letting the abstract class call them from an implementation of other methods.
Here is an example:
class AbstractToy {
protected abstract String getName();
protected abstract String getSize();
public String getDescription() {
return "This is a really "+getSize()+" "+getName();
}
}
class ToyBear extends AbstractToy {
protected override String getName() { return "bear"; }
protected override String getSize() { return "big"; }
}
class ToyPenguin extends AbstractToy {
protected override String getName() { return "penguin"; }
protected override String getSize() { return "tiny"; }
}
Note how AbstractToy
's implementation of getDescription
is able to call getName
and getSize
, even though the definitions are in the subclasses. This is an instance of a well-known design pattern called Template Method.
The abstract method definition in a base type is a contract that guarantees that every concrete implementation of that type will have an implementation of that method.
Without it, the compiler wouldn't allow you to call that method on a reference of the base-type, because it couldn't guarantee that such a method will always be there.
So if you have
MyBaseClass x = getAnInstance();
x.doTheThing();
and MyBaseClass
doesn't have a doTheThing
method, then the compiler will tell you that it can't let you do that. By adding an abstract doTheThing
method you guarantee that every concrete implementation that getAnInstance()
can return has an implementation, which is good enough for the compiler, so it'll let you call that method.
Basically a more fundamental truth, that needs to be groked first is this:
You will have instances where the type of the variable is more general than the type of the value it holds. In simple cases you can just make the variable be the specific type:
MyDerivedClassA a = new MyDerivcedClassA();
In that case you could obviously call any method of MyDerivedClassA
and wouldn't need any abstract methods in the base class.
But sometimes you want to do a thing with any MyBaseClass
instance and you don't know what specific type it is:
public void doTheThingsForAll(Collection<? extends MyBaseClass> baseClassReferences) {
for (MyBaseClass myBaseReference : baseClassReferences) {
myBaseReference.doTheThing();
}
}
If your MyBaseClass
didn't have the doTheThing
abstract method, then the compiler wouldn't let you do that.