Скачать презентацию Item 16 Favor composition over inheritance Inheriting Скачать презентацию Item 16 Favor composition over inheritance Inheriting

Item 16.pptx

  • Количество слайдов: 9

Item 16: Favor composition over inheritance Item 16: Favor composition over inheritance

Inheriting from ordinary concrete classes across package boundaries is dangerous. Inheritance violates encapsulation! Inheriting from ordinary concrete classes across package boundaries is dangerous. Inheritance violates encapsulation!

// Broken - Inappropriate use of inheritance! public class Instrumented. Hash. Set < E // Broken - Inappropriate use of inheritance! public class Instrumented. Hash. Set < E > extends Hash. Set < E > { // The number of attempted element insertions private int add. Count = 0 ; public Instrumented. Hash. Set ( ) { } public Instrumented. Hash. Set ( int init. Cap, float load. Factor ) { super ( init. Cap, load. Factor ) ; } @Override public boolean add ( E e ) { add. Count ++; return super. add ( e ) ; } @Override public boolean add. All ( Collection c ) { add. Count += c. size ( ) ; return super. add. All ( c ) ; } public int get. Add. Count ( ) { return add. Count ; } }

Instrumented. Hash. Set < String > s = new Instrumented. Hash. Set < String Instrumented. Hash. Set < String > s = new Instrumented. Hash. Set < String > ( ) ; s. add. All ( Arrays. as. List ( "Snap" , "Crackle" , "Pop" ) ) ;

get. Add. Count() returns 6, not 3!!! get. Add. Count() returns 6, not 3!!!

Bad fixes: • Eliminate overriding of add. All() method. (There is no guaranty of Bad fixes: • Eliminate overriding of add. All() method. (There is no guaranty of keeping this implementation in further versions of Java) • Totally override add. All() method. (Difficult, time-consuming, and error-prone; not always possible, as some methods cannot be implemented without access to private fields inaccessible to the subclass)

Other problems: • In new version superclass has got a new method that adds Other problems: • In new version superclass has got a new method that adds elements – elements added via this method aren’t count; • In new version superclass has got a method with the same signature but different return type – it causes compilation error. • In new version superclass has got a method with the same signature – it causes overriding, it is doubtful that your method will fulfill the contract of the new superclass method.

// Wrapper class - uses composition in place of inheritance public class Instrumented. Set // Wrapper class - uses composition in place of inheritance public class Instrumented. Set < E > extends Forwarding. Set < E > { private int add. Count = 0 ; public Instrumented. Set ( Set < E > s ) { super ( s ) ; } @Override public boolean add ( E e ) { add. Count ++; return super. add ( e ) ; } @Override public boolean add. All ( Collection c ) { add. Count += c. size ( ) ; return super. add. All ( c ) ; } public int get. Add. Count ( ) { return add. Count ; } }

// Reusable forwarding class public class Forwarding. Set<E> implements Set<E> { private final Set<E> // Reusable forwarding class public class Forwarding. Set implements Set { private final Set s; public Forwarding. Set(Set s) { this. s = s; } public void clear() { s. clear(); } public boolean contains(Object o) { return s. contains(o); } public boolean is. Empty() { return s. is. Empty(); } public int size() { return s. size(); } public Iterator iterator() { return s. iterator(); } public boolean add(E e) { return s. add(e); } public boolean remove(Object o) { return s. remove(o); } public boolean contains. All(Collection c) { return s. contains. All(c); } public boolean add. All(Collection c) { return s. add. All(c); } public boolean remove. All(Collection c) { return s. remove. All(c); } public boolean retain. All(Collection c) { return s. retain. All(c); } public Object[] to. Array() { return s. to. Array(); } public T[] to. Array(T[] a) { return s. to. Array(a); } @Override public boolean equals(Object o) { return s. equals(o); } @Override public int hash. Code() { return s. hash. Code(); } @Override public String to. String() { return s. to. String(); } }