среда, 1 августа 2012 г.

oop: inheritance+delegation

    В объектно-ориентированных языках есть два основных метода образовывать композиции из классов (увязывать их вместе) - наследование и делегирование.

    Наследование
    Наследование позволяет достигнуть двух целей:
    - получение интерфейса (от класса/интерфейса)
    - получение реализации (от класса/(с Java 8 - интерфейса))

    public class ArrayList implements List extends AbstractList
Хотим "быть листом"
    List<String> words = new ArrayList<>(16);
И при этом реализацию метода size() получить от AbstractList.

    class Oval implements Figure {...}
Хотим иметь List<Figure> с Oval, Rect, ...    
Хотим иметь методы работающие с Figure и коллекциями фигур List<Figure>, хотим насладится полиморфизмом на основе наследования

    public class BufferedInputStream extends InputStream 
Хотим заменять InputStream

Правильно наследуются в следующих случаях:
- реализация размазана по иерархии - AbstractCollection, AbstractList, ...
- реализация не доделана и ждет нас - TemplateMethod (InputStream)
- реализация доделана, но открыта к расширению - LinkedHashMap
- Hibernate наследует bean
- Spring влезает к нам под интерфейс для tx, security, logging
- маркер интерфейс - RandomAccess, Cloneable, Serializable

Неправильно наследуются в следующих случаях:
- ситуативно (extends ArrayList для перекрытия add, но забыли про addAll)
- бытовая интуиция (Square ex Rect, Rect ex Square) + (Rect - Parallelogram)
- глупое обобщение - Idible {long getId()} - все объекты в системе с Id


    Делегирование
    Делегирование решает проблемы:
    - большое количество комбинаций качеств - комбинация Декораторов
    - динамическое изменение поведения - State / Strategy

    Существуют и другие способы образовывать композиции в ООП:
    - ??? слаботипизированная композиция по аннотациям (JUnit, Servlet API 3, ?)
    - ??? Mockito - на основе правил


    Существуют и другие способы образовывать композиции в не-ООП:
    - функциональные ???