Поскольку смешивание в чертах выполняется статически в Scala, если вы хотите изменить черты, смешанные с объектом, создайте различные объекты на основе некоторого условия.
Давайте рассмотрим пример канонического торта. Ваши модули определены как черты, а ваше приложение построено как простой объект с набором функциональных возможностей, смешанных в
val application =
new Object
extends Communications
with Parsing
with Persistence
with Logging
with ProductionDataSource
application.startup
Теперь у всех этих модулей есть хорошие объявления собственных типов, которые определяют их межмодульные зависимости, так что строка компилируется только в том случае, если существуют все ваши межмодульные зависимости, уникальны и хорошо типизированы. В частности, модуль «Постоянство» имеет собственный тип, который говорит, что все, что реализует «Постоянство», должно также реализовывать DataSource, абстрактную черту модуля. Поскольку ProductionDataSource наследуется от DataSource, все отлично, и эта строка построения приложения компилируется.
Но что, если вы хотите использовать другой источник данных, указывающий на некоторую локальную базу данных для целей тестирования? Предположим далее, что вы не можете просто повторно использовать ProductionDataSource с другими параметрами конфигурации, загруженными из файла некоторых свойств. В этом случае вы должны определить новую черту TestDataSource, которая расширяет DataSource, и вместо этого смешать ее. Вы даже можете сделать это динамически, основываясь на флаге командной строки.
val application = if (test)
new Object
extends Communications
with Parsing
with Persistence
with Logging
with TestDataSource
else
new Object
extends Communications
with Parsing
with Persistence
with Logging
with ProductionDataSource
application.startup
Теперь это выглядит немного более многословно, чем хотелось бы, особенно если вашему приложению нужно изменять свою структуру по нескольким осям. С положительной стороны, у вас обычно есть только один кусок условной логики построения, такой же, как в приложении (или, в худшем случае, один раз на жизненный цикл идентифицируемого компонента), поэтому, по крайней мере, боль сводится к минимуму и отгораживается от остальной части вашей логики.