有人问了一些与这个问题有些相关的问题,但这些问题似乎不太合适。
我使用Cake模式将"存储"系统滑入生产代码中,并将存根存储系统滑入以进行测试。这一切都很好,但有一个类正在原始类中实例化,它也需要混合这个存根存储系统。由于它隐藏在实现中,我无法访问它。
事情看起来是这样的:
class Main { this: Storage =>
...
val used = Used(...)
...
}
class Used { this: Storage =>
...
}
当测试"已用"时,我只需new Used with StubStorage
,然后关闭。我曾经对Main
做过同样的事情,但那是在它使用Used
之前。既然Main
对Used
进行了简单的实例化,我就遇到了这个问题。
我想这样试试:
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
}
但这当然不起作用,因为编译器没有足够的信息来发现T
。有什么神奇的配方吗?我已经玩了一段时间,它看起来很麻烦,标准OO注入方法实际上没有那么麻烦,但我可能会错过一些东西。
我已经研究过隐含的工厂概念,但我无法将其转化为用于混合的形状。
编辑:公开撰写问题的清晰度令人惊讶。:)我还没有按照我最初打算的方式解决这个问题,但有一个简单的解决实际问题的方法:
trait UsedProvider {
def createUsed = Used.apply _
}
class Main { this: Storage with UsedProvider =>
val used = createUsed(...)
}
那么我只需要在测试中做以下操作:new Main with StubStorage with StubUsedProvider
。
我也没有解决您最初的问题,但您是否考虑过为Main
使用抽象类,并在需要的地方为used
提供值?
abstract class Main { this: Storage =>
val s = "s"
val used: Used
}
然后像这样实例化:
val main = new Main with StubStorage { val used = new Used(s) with StubStorage }