Я думаю о том, как структурировать некоторый код в Scala, который имеет признаки, зависящие от других признаков, и мне интересно, является ли внедрение зависимостей с самопечатанием лучшим подходом для этого.
В приведенном ниже примере кода черта Adder
ссылается на функциональность черты HasLogger
посредством самописи. Класс Doubler
расширяется Adder
и, следовательно, также требует HasLogger
. Класс Foo
также требует HasLogger
для Adder
, но также использует его напрямую.
Если бы мы изменили один из классов так, чтобы он больше не использовал Adder
, как бы мы узнали можем ли мы также удалить HasLogger
? (В этом случае это легко проверить, но со многими зависимостями это не будет очевидно). Также, если бы было много классов, подобных Doubler
, был бы повторяющийся код, поскольку каждый из них должен был бы расширять как HasLogger
, так и Adder
. Это ситуация, когда Adder
следует расширять HasLogger
вместо использования самонабора?
trait HasLogger {
val logger: Logger = new Logger
class Logger {
def log(msg: String): Unit = println(msg)
}
}
trait Adder {
this: HasLogger =>
def add(x: Int, y: Int): Int = {
logger.log(s"Adding $x and $y")
x + y
}
}
class Doubler extends HasLogger with Adder {
def double(x: Int): Int = add(x, x)
}
class Foo extends HasLogger with Adder {
def logInt(x: Int): Unit = logger.log(x.toString)
def add3(x: Int, y: Int, z: Int): Int = add(add(x, y), z)
}