Item 16: Favor composition over inheritance

1.  Inheriting from ordinary concrete classes across package boundaries is dangerous.

 

2.  Unlike method invocation, inheritance violates encapsulation. The superclass’s implementation may change from release to release, and if it does, the subclass may break, even though its code has not been touched.

 

3.  HashSet’s addAll method is implemented on top of its add method, although HashSet, quite reasonably, does not document this implementation detail.

 

4.  A related cause of fragility in subclasses is that their superclass can acquire new methods in subsequent releases.

 

5.  Instead of extending an existing class, give your new class a private field that references an instance of the existing class. This design is called composition because the existing class becomes a component of the new one. Each instance method in the new class invokes the corresponding method on the contained instance of the existing class and returns the results. This is known as forwarding, and the methods in the new class are known as forwarding methods.

 

6.  A wrapper class is also known as the Decorator pattern.

 

7.  Sometimes the combination of composition and forwarding is loosely referred to as delegation. Technically it’s not delegation unless the wrapper object passes itself to the wrapped object(so that wrapped object can pass it to other objects instead of passing the wrapped object itself.)

 

8.  Wrapper classes are not suited for use in callback frameworks, wherein objects pass self–references to other objects for subsequent invocations (“callbacks”). Because a wrapped object doesn’t know of its wrapper, it passes a reference to itself (this) and callbacks elude the wrapper.

 

9.  Inheritance is appropriate only if an “is-a” relationship exists between the two classes.

 

10.  The wrapped class actually is the implementation detail of the wrapping class. If you use inheritance where composition is appropriate, you needlessly expose implementation details. The resulting API ties you to the original implementation, forever limiting the performance of your class. More seriously, by exposing the internals you let the client access them directly. At the very least, this can lead to confusing semantics.

 

11.  If p refers to a Properties instance, then p.getProperty(key) may yield different results from p.get(key): the former method takes defaults into account, while the latter method, which is inherited from Hashtable, does not. In the case of Properties, the designers intended that only strings be allowed as keys and values, but direct access to the underlying Hashtable allows this invariant to be violated.

 

12.  Inheritance propagates any flaws in the superclass’s API, while composition lets you design a new API that hides these flaws.

你可能感兴趣的:(Decorator,Effective Java,inheritance,Composition)