Using self-type for dependency injections, cause to expose public method of other traits ,which break the single responsibility principal. Let's me talk with example
trait Output {
def output(str: String): Unit
}
trait ConsoleOutput extends Output {
override def output(str: String): Unit = println(str)
}
class Sample {
self: Output =>
def doSomething() = {
// I do something stupid here!
output("Output goes here!")
}
}
val obj = new Sample with ConsoleOutput
obj.output("Hey there")
My Sample class dependes on Output trait and of course I would like to use Output trait methods in my Sample class. But with above code example my Sample class expose output method which doesn't come from its functionality and break single responsibility of Sample.
How can I avoid it and keep using self-type and cake-pattern?
Responsibility of providing the output still lies with the component implementing
Output. The fact that your class provides access to it is no different from something like:Sure, you can make
outprivate here, but you could also have.outputprotected inConsoleOutputif you don't want it accessible from outside as well.(The answer to your comment in the other answer is that if you also want to use it "stand-alone", then you subclass it, and make
outputpublic in the subclass).