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:
class Foo(val out: Output)
new Foo(new ConsoleOutput{}).out.output
Sure, you can make out
private here, but you could also have .output
protected in ConsoleOutput
if 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 output
public in the subclass).