Check this out:
http://www.angelfire.com/tx4/cus/shapes/java.html
Ther's an abstract class Shape. Technically, it's possible to remove abstract keyword from it. In this case you must specify what would be the body of the method Shape.draw() - and it's where comes that error-proneness and non-readability that I've mentioned.
First, your Shape would become instantiable. This means that it's possible to have instances of runtime type Shape in your app. What does Shape means in terms of your subject area? It's meaningless as an instantiable type. It has no sense similarly as such instruction has no sense: 'go to market and buy (instantiate) vegetable'. What exactl vegetable should be bought? But if you want not to instantiate, but manipulate with such type, then it makes sense: 'go to market and buy (instantiate) two cucumbers, one orange, and some cherries. Make a salad (call some methods that are defined for Vegetable type) of all vegetables (abstract type)'.
Secondly, what should be the implementation of the Shape.draw() method? As I've said earlier, you must provide implementation for non-abstract method. Maybe in this example it's suitable to say that empty body implementation is OK. But think of the abstract class DatabaseConnectionFactory, what createNewConnection() implementation should be there - with MySql driver or MongoDB? In this case answer is not so obvious and impossible, imho.
Thirdly, you won't get error at compile time if you create a subclass of Shape, let's say Rectangle, and not override method draw(). Just because you forgot, missed it. It could happen because you may override it or may not override it. And you would get rectangles that do not draw themselves in your app. While this may sound simple in this example, it may have much more severe consequences in more complex scenario where this mistake doesn't reveal itself in such obvious way. But if you would use abstract class for Shape, just as in example, and forget to implement draw() in Rectangle, you would get a compile error. abstract method signature literally says that Shape needs to be drawn but on this level of abstraction it's unknown how to do this, each subclass must define how to do it for it's particular implementation.
Fourthly, and most important - it's semantics. Abstract type (either interface or abstract class) defines some common but not all behavior. And its abstractness indicates that this behavior is partial - there should be more specifics that will be specified in subclasses. Thus everybody who reads your code understands your intention more clearly rather if you would use only non-abstract classes.
And abstract class is semantically "interface + partial implementation". So if you understand what's the purpose of interfaces, then the purpose of abstract classes is the same + to give common partial implementation that could be re-used in subclasses. It's specific to Java to not allow inherit from multiple abstract classes - this design is for preventing problems that could arise with this, but this restriction doesn't change the meaning of abstract class. There're languages that allow mutiple inheritance or even provide a better concept - Trait.
Thanks again for sparing time to teach me❤️
Обсуждают сегодня