Effective Java (Joshua Bloch) Item 17 says :
"Design and Document or inheritance or else prohibit it"
However, just a cursory glance through the Android APIs reveals that most of the API classes are non-final; which is OK if they are also documented for inheritance (View
of Activity
, for example). But there are also several non-final classes, but the documentation makes no mention about the inheritability of these classes. Just some arbitrary examples to illustrate my point:
WifiManager
, NotificationManager
...)UriMatcher
.Camera
.Openness and extensibility being the philosophy of Android, is the convention reversed here? Meaning, could one assume that all of the Android API classes are designed to be inherited (whether explicitly documented or otherwise); unless declared final?
In Kotlin, unlike Java, all the classes are implicitly marked final by default. If you want to inherit from a class, you have to explicitly add open keyword before the class declaration.
Java doesn't support multiple inheritances in classes because it can lead to diamond problem and rather than providing some complex way to solve it, there are better ways through which we can achieve the same result as multiple inheritances.
What cannot be inherited ? Constructors. Although, the subclass constructor has to call the superclass constructor if its defined (More on that later!) Multiple classes.
A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.
Just my €0,02: Clean OO design by the book is one thing, making things work for all possible use cases in practice is another. The principles of clean OO design sometimes are somewhat of academic nature. - And maybe a little bit of black and white.
Think for instance about who uses the Android API provided by google: It's not only app developers but also device manufacturers who need to specialize general APIs for their devices.
So, for me, SW design is neither black nor white in most cases; the shades of grey are important.
And finally: In practice I have seldom (read: never) seen problems caused by "carelessly" omitted final
keywords (on classes), while unreflected overuse of final
(often caused by thoughts like "my code is sooo [great | ugly], no one will actually ever want to modify it through inheritance") can be quite a pain.
"I know that I know nothing" seems to fit here: It is presumptuous to claim that one knows all the crazy, ingenious, creative, smart,... ideas of others for how one's code may be used in the future beforehand.
The Android developers went to great lengths to ensure that extensibility, while not recommended in many cases, is possible. The motivation behind this appears to be related to testing environments.
For instance, it would be much more difficult to create a faux WifiManager
for the purposes of creating unit tests if it were finalized. Without the finalization, it is trivial to subclass the WifiManager
(e.g. to mimic "unexpected" wifi disconnection during operation) and return an instance of this subclass from a customized testing Context
.
So while you will probably never find a reason to implement a subclass of the these classes in an application that you ship to the end users, the flexibility is there to allow you to extend them if it is necessary for one reason or another.
In the case of utility classes, the answer is simply that the utility of the class is not diminished by allowing the developer to subclass; in many cases, a developer can achieve more understandable code reuse by inheritance than by aggregation and delegation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With