Effective Java 3rd Edition, Clause 18: Composition preference over inheritance describes the problem of using inheritance to add behavior to a class:
A related reason for fragility in subclasses is that their superclass may acquire new methods in subsequent releases. Suppose that a program depends on its security on the fact that all elements inserted into a collection satisfy a predicate. This can be guaranteed by subclassing the collection and overriding each method that can add an element to ensure that the predicate is executed before the element is added. This works fine until a new method capable of inserting an element is added to the superclass in a subsequent release. Once this happens, it becomes possible to add an “illegal” element simply by calling a new method that is not overridden in a subclass.
Recommended Solution:
Instead of extending an existing class, give your new class a private field that refers to an instance of an existing class ... Each instance method in a new class calls the corresponding method in the containing instance of the existing class and returns Results. This is known as forwarding, and the methods in the new class are known as forwarding methods ... adding new methods to an existing class will have nothing to do with the new class ... You need to write forwarding methods, but you must write a reusable forwarding class for each interface only once, and you can be given redirect classes. For example, Guava provides forwarding classes for all collection interfaces.
: , , ? , Guava, - , ?
, , , , -. , .
Guava, -, "-" , . , ; , , :
, , ForwardingMap.put ForwardingMap.putAll. , , , , .
ForwardingMap.put
ForwardingMap.putAll
, , Guava - .
, , ?
, , , . ( ), , .
Since you own the forwarding class, you can add new methods to it, thereby preserving the invariant.