私の質問はScala Cake Pattern and Dependency Collisionsと非常によく似ています。しかし、私はDaniel Cの答えに示唆されているような具体的な解決策を見つけるのに苦労しています。Scala Cake Pattern:依存関係の衝突を避けるには?
ProductDetailsPage
(特性)がそれぞれProductServiceModuleWs
とSessionModuleWs
によって実装二つの独立したサービスモジュールProductServiceModule
とSessionModule
が、必要です。
だからここで問題です。
どちらのモジュールもRestServiceConfigurationProvider
に依存しています。
RestServiceConfigurationProvider
の場合、具体的な実装はDefaultRestServiceConfigurationProvider
(atm)しかありません。
一方DefaultRestServiceConfigurationProvider
はProductServiceModuleWs
、要するにHybrisEndpointProvider
又はProductServiceEndpointProvider
こととSessionModuleWs
リモートRESTful Webサービスに接続するかRestEndpointProvider
に依存します。特定のサービスの正確なIPアドレスは、RestEndpointProviderの実装によって提供されます。
ここで、衝突が発生します。下のコードを試してみてください。依存関係の衝突が発生する面倒なところは、コメントでマークされています。当然
ので、コンパイラはRestEndpointProvider
の相反する2つの実装を訴え、すなわちHybrisEndpointProvider
とProductServiceEndpointProvider
ダニエルはどのような衝突を避けるために、彼の答えで述べたように、私は、別途ProductServiceModuleWs
とSessionModuleWs
を配線しなければなりません私が捕まってしまったところ、おそらくそう
new ProductServiceModuleWs
with DefaultRestServiceConfigurationProvider
with ProductServiceEndpointProvider
new SessionModuleWs
with DefaultRestServiceConfigurationProvider
with HybrisEndpointProvider
しかし、ここのような独自の具体的なRestEndpointProvider実装とそれぞれが、あります。
これらの2つの個別に構成されたモジュールは、どのようにして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 !!!!!
}
}
私はあなたの例から多くを学んだ、ありがとう。 – simou