In your specific case, where you have 2 methods which don't return anything, it may be alright to do what you're doing. It's kind of flirting on the edges of the null object pattern, but not quite. There's nothing stopping you from doing it that way; it will compile. In some designs, it may even be a good choice. Your example is too contrived to say whether or not it's a good idea.
Suppose you have a method which returns a value, though. You can't just put a comment //do nothing
because you need a return to satisfy the compiler. So you add a sentinel value. This is pretty error prone, as it relies on callers being aware of the values which have special meanings. It may even be the case that no suitable sentinel value even exists, if the set of genuine results contains every possible value.
class Base {
void methodA() {
//empty
}
int getFoo() {
// Don't do this, just an example
return -1;
}
}
Someone might instantiate new Base()
and not realise that their code is destined to be useless, and that the class's author intended for them to instantiate Sub
or another child class. They might not know they're supposed to check sentinel values, etc.
It would be better in this case if they couldn't do that. It would be better to mark Base
as an incomplete implementation, and tell the compiler that it must be completed to be any use. This is precisely what abstract classes are for.
By marking a class as abstract, you are telling the compiler that users are not allowed to instantiate this class because, for whatever reason, doing so does not make sense.
By marking a method as abstract, you are telling the compiler that a child class must provide an implementation in order to itself be instantiable (the child class could also be abstract, kicking the can down the road to child class of itself to provide an implementation).
abstract class Base {
void methodA() {
//empty
}
abstract int getFoo();
}
TL;DR your one specific example does not prove that abstract classes have no utility.