Вы должны быть осторожны с тем значением, которое вы придаете композиции. В более общем смысле черты являются механизмом как разложения, так и состава.
- Разложение - как мы разлагаем программную базу на подходящие единицы
повторного использования (повторное использование кода, СУХОЙ).
- Композиция - как мы составляем эти единицы для получения иерархии классов
подходит для нашего приложения домена.
Черты - это механизм для композиции в том смысле, что они могут быть составлены с помощью класса. Многие реализации признаков также позволяют составлять признаки друг с другом.
Мантра GoF - «композиция благосклонности перед наследованием».
Все языки классов по умолчанию предпочитают наследование. Объект может приобретать поведение только у своего класса или у классов выше в цепочке наследования. Конечно, вы можете достичь одного и того же результата по-разному. Например, вы можете создать класс диспетчера (например, LayoutMananager), а затем добавить ссылку на него в любом классе, обладающем чертой поведения / макета, и добавить функцию, которая не выполняет ничего, кроме вызова методов диспетчера
public function doSomething() { return layoutManager.doSomething(); }
Черты благоприятствуют композиции. Просто как тот. Ключевой характеристикой черт является то, что они живут вне иерархии классов. Вы можете «приобретать» многократно используемые модели поведения или черты, не используя их ни в одном из ваших суперклассов (различие по горизонтали и вертикали, представленное в других публикациях). Это главное преимущество.
Самая большая проблема с признаками - это возникновение конфликта, когда признаки реализованы таким образом, что вы можете напрямую выполнить myObject.doSomething () вместо myObject.trait1.doSometing () (прямо или косвенно, как описано выше с layoutManager) , Как только вы добавите более одной черты в класс, конфликты могут легко возникнуть. Ваша реализация должна поддерживать такие механизмы, как псевдонимы и переопределения, чтобы помочь в разрешении конфликтов. Вы получаете некоторые накладные расходы обратно.
Не ясно, соответствует ли реализация PHP этому, но черты также не должны указывать какие-либо переменные экземпляра, и методы, предоставляемые чертами, никогда не должны напрямую обращаться к переменным экземпляра. (источник: Добавление признаков к (статически типизированным) языкам , PDF). Это сообщение в блоге обсуждает это. Он утверждает, что в PHP структура с именем trait действительно является смесью (то есть признаками с состоянием). (Хотя этот другой пост в блоге описывает их как не имеющих состояния )
В целом, мышление в терминах черт может помочь в написании лучшего кода. Написание классов черт, чтобы избежать инстанцирования, также может способствовать улучшению кода. Это освобождает черты от любой зависимости, позволяя вызывать их в любом порядке. Но не ясно, что добавление понятия черты в сам язык будет способствовать улучшению кода.