Черты являются еще одним способом сделать композицию. Думайте о них как о способе составления всех частей класса во время компиляции (или JIT-компиляции), собирая конкретные реализации частей, которые вам понадобятся.
По сути, вы хотите использовать черты, когда вы делаете уроки с различными комбинациями функций. Эта ситуация возникает чаще всего для людей, пишущих гибкие библиотеки для других. Например, вот объявление класса модульного теста, который я недавно написал с использованием ScalaTest :
class TestMyClass
extends WordSpecLike
with Matchers
with MyCustomTrait
with BeforeAndAfterAll
with BeforeAndAfterEach
with ScalaFutures
Раздел рамки испытаний имеют массу различных вариантов конфигурации, и каждая команда имеет разные предпочтения о том , как они хотят , чтобы делать вещи. Помещая параметры в черты (которые смешиваются при использовании with
в Scala), ScalaTest может предложить все эти опции без необходимости создавать имена классов, например WordSpecLikeWithMatchersAndFutures
, или тонну логических флагов времени выполнения, подобных WordSpecLike(enableFutures, enableMatchers, ...)
. Это позволяет легко следовать принципу « открыто / закрыто» . Вы можете добавлять новые функции и новые комбинации функций, просто добавив новую черту. Это также облегчает следование принципу сегрегации интерфейса , потому что вы можете легко поместить функции, которые не всегда необходимы, в черту.
Черты также являются хорошим способом поместить общий код в несколько классов, которые не имеют смысла разделять иерархию наследования. Наследование - это очень тесно связанные отношения, и вы не должны оплачивать эти расходы, если можете помочь. Черты - намного более слабосвязанные отношения. В моем примере выше я MyCustomTrait
легко делил реализацию фиктивной базы данных между несколькими иначе не связанными тестовыми классами.
Внедрение зависимостей позволяет достичь многих из тех же целей, но во время выполнения на основе пользовательского ввода, а не во время компиляции на основе ввода программиста. Черты также предназначены больше для зависимостей, которые семантически являются частью одного и того же класса. Вы как бы собираете части одного класса, а не вызываете другие классы с другими обязанностями.
Инъекционное Dependency рамки достижение многих из тех же целей во время компиляции на основе ввода программиста, но в основном обходной путь для языков программирования без надлежащей поддержки признака. Черты привносят эти зависимости в область средства проверки типов компилятора с более чистым синтаксисом и более простым процессом сборки, что делает более четкое различие между зависимостями времени компиляции и времени выполнения.