There have been some questions asked that are somewhat related to this problem, but they don't seem to fit quite right.
I'm using the Cake pattern to slide a "Storage" system in place in production code, and a stub storage system in for testing purposes. This is all great, but there's a class that's being instantiated within the original class that also needs to have this stub storage system mixed in. Since it's hidden inside the implementation, I don't have access to it.
Things look like this:
class Main { this: Storage =>
...
val used = Used(...)
...
}
class Used { this: Storage =>
...
}
When testing "Used" I simply new Used with StubStorage
and off I go. I used to do the same with Main
but that was before it made use of Used
. Now that Main
makes a naive instantiation of Used
I've got this problem.
I wanted to try it this way:
class Main[T <: Storage] { this: T =>
...
val used = Used[T](...)
...
}
class Used[T <: Storage] { this: T =>
...
}
object Used {
def apply[T <: Storage](...) = new Used(...) with T
}
But of course that doesn't work because the compiler doesn't have enough information to discover T
. Is there a magic recipe for this? I've played around with it f开发者_如何学运维or a bit and it seems to be cumbersome enough that the standard OO injection method is actually less trouble, but I could be missing something.
I've looked at the implicit Factory concept but I can't pound that into shape to work for mixins.
EDIT: It's amazing the clarity that writing the question publicly gives. :) I haven't solved the problem the way I originally intended, but there is a simple solution to the actual problem:
trait UsedProvider {
def createUsed = Used.apply _
}
class Main { this: Storage with UsedProvider =>
val used = createUsed(...)
}
Then I would just do the following in the test: new Main with StubStorage with StubUsedProvider
.
I haven't solved your original problem either but have you considered using an abstract class for Main
and provide the value for used
where you need it?
abstract class Main { this: Storage =>
val s = "s"
val used: Used
}
Then instantiate like this:
val main = new Main with StubStorage { val used = new Used(s) with StubStorage }
精彩评论