|
Do yourself a favor and wear yourself off all this SOLID, Uncle Bob, Object Oriented, Clean Code crap. Don't ever use inheritance. Instead of things inheriting from other things, flip the relationship and make things HAVE other things. This is called composition and it has all the positives of inheritance but none of the negatives. Example: imagine you have a school system where there are student users and there are employee users, and some features like grading that should only be available for employees. Instead of making Student and Employee inherit from User, just have a User class/record/object/whatever you want to call it that constitutes the account data class User (id: Int, name: String, email: String)
and for those Users who are students, create a Student that points to the user data class Student (userId: Id, blabla student specific attributes)
and vice versa for the Employees data class Employee (userId: Id, blabla employee specific attributes)
then, your types can simply and strongly prevent Students from being sent into functions that are supposed to operate on Employees etc etc (but for those cases where you really want functions that operate on Users, just send in each of their Users! nothing's preventing you from that flexibility if that's what you want)and for those users who really are both (after all, students can graduate and become employees, and employees can enroll to study), THE SAME USER can be BOTH a Student and an Employee! (this is one of the biggest footguns with inheritance: in the inheritance world, a Student can never be an Employee, even though that's just an accident of using inheritance and in the real world there's actually nothing that calls for that kind of artificial, hard segregation) Once you see it you can't unsee it. The emperor has no clothes. Type-wise functional programmers have had solutions for all these made up problems for decades. That's why these days even sane Object Oriented language designers like Josh Bloch, Brian Goetz, the Kotlin devs etc are taking their languages in that direction. |
There will be times when you want to represent Is-A relationship - especially when you want to guarantee a specific interface/set of functions your object will have - irrespective of the under the hood details.
Here what you care about is notifier providing a set of functions (sendNotification, updateNotification, removeNotification) - irrespective of what the implementation details are - whether you're using desktop notifications or SMS notifications.