我的问题与Scala Cake Pattern 和 Dependency Collisions非常相似。但我正在努力寻找 Daniel C 的回答中建议的具体解决方案。
所以这里是问题:
A ProductDetailsPage
(trait) 需要两个独立的服务模块ProductServiceModule
和SessionModule
,分别由ProductServiceModuleWs
和实现SessionModuleWs
。
这两个模块都依赖于RestServiceConfigurationProvider
.
为此RestServiceConfigurationProvider
,只有一个具体的实现可用:DefaultRestServiceConfigurationProvider
(atm)。
DefaultRestServiceConfigurationProvider
另一方面取决于RestEndpointProvider
哪个可以是 a或HybrisEndpointProvider
aProductServiceEndpointProvider
简而言之,ProductServiceModuleWs
并SessionModuleWs
连接到远程 RESTful Web 服务。特定服务的确切 IP 地址由 RestEndpointProvider 的实现提供。
现在,这就是发生碰撞的地方。随意尝试下面的代码。发生依赖冲突的麻烦地方由注释标记。
理所当然地,编译器抱怨 的两个相互冲突的实现RestEndpointProvider
,即HybrisEndpointProvider
和ProductServiceEndpointProvider
正如丹尼尔在他的回答中提到的那样,为避免任何此类冲突,我应该分别连接ProductServiceModuleWs
and SessionModuleWs
,每个都有自己的具体 RestEndpointProvider 实现,也许像这样
new ProductServiceModuleWs
with DefaultRestServiceConfigurationProvider
with ProductServiceEndpointProvider
new SessionModuleWs
with DefaultRestServiceConfigurationProvider
with HybrisEndpointProvider
但这是我卡住的地方。
现在如何将这两个单独配置的模块注入到ProductDetailsPage
避免依赖冲突中,但仍然使用蛋糕模式?
这是示例代码。该代码是自包含的,应该在您的 IDE 中运行。
case class RestEndpoint(url: String, username: Option[String] = None, password: Option[String] = None)
trait RestEndpointKey {
def configurationKey: String
}
case object HybrisEndpointKey extends RestEndpointKey { val configurationKey = "rest.endpoint.hybris" }
case object ProductServiceEndpointKey extends RestEndpointKey { val configurationKey = "rest.endpoint.productservice" }
trait ProductDetailsPage {
self: ProductServiceModule with SessionModule =>
}
trait ProductServiceModule {}
trait SessionModule {}
trait ProductServiceModuleWs extends ProductServiceModule {
self: RestServiceConfigurationProvider =>
}
trait SessionModuleWs extends SessionModule {
self: RestServiceConfigurationProvider =>
}
trait RestServiceConfigurationProvider {}
trait DefaultRestServiceConfigurationProvider extends RestServiceConfigurationProvider {
self: RestEndpointProvider =>
}
sealed trait RestEndpointProvider {
def endpointKey: RestEndpointKey
}
trait HybrisEndpointProvider extends RestEndpointProvider {
val endpointKey = HybrisEndpointKey
}
trait ProductServiceEndpointProvider extends RestEndpointProvider {
val endpointKey = ProductServiceEndpointKey
}
object Example extends App {
new ProductDetailsPage
with ProductServiceModuleWs
with SessionModuleWs
with DefaultRestServiceConfigurationProvider
with HybrisEndpointProvider
with ProductServiceEndpointProvider /// collision, since HybrisEndpointProvider already defined the endpointKey !!!!!
}
}