@final tag/comment on the Reusable Shared Logics in the Abstract object<aside> 💡
In Go, even though it can use Anonymous Embedding to mimic inheritance, but it is not idiomatic. The Reusable Shared Logics should be a helper function or re-implement in concrete objects instead of a method in Abstract object.
Example:
If the object we're inheriting is a concrete component (not an abstract base class), it could cause problems.
This principle holds true especially in Structural Patterns, where the goal is to wrap concrete objects**,** not to extend abstractions.
In TypeScript, when two superclasses have a common ancestor, method or property.
Class A -> method()
Class B extends A -> method()
Class C extends A -> method()
Class D extends B, C -> ??? (Which method() to use?)
e.g., If we use Inheritance in Facade pattern
In Java, it disallows multiple inheritance of classes.
In Go, the conflict of anonymous embedding multiple types, the compiler throws an ambiguity error. Anonymous Embedding
The wrapping behaviour by Inheritance can not be done at runtime. Hard-coding all possible wrapping is dirty.
e.g., If we use Inheritance in Decorator pattern
Even though the wrapping behaviour is not going to wrap multiple concrete objects or be at runtime. Wrapping behaviour via inheritance tightly is defying the SOLID’s Dependency Inversion Principle (DIP), which favor abstraction dependencies.
e.g., If we use Inheritance in Proxy and Adapter patterns
Even though we are not wrapping an object but making an abstract object for concrete objects, if there are no Reusable Shared Logics, the coupling is unnecessary.