I have a case where a interface SubscriptionService
have a generic type <T: SubscriptionPatch>
. Following, I have a service that injects all implementations of SubscriptionService
in a list, but Spring cannot resolve theses dependencies without variance operator out
. Using out
operator solve the problem, but I can’t call functions with parameters of generic type (out
restricts the generic only to output type). Example code:
@SpringBootApplication
class ResolveDependencyApplication
fun main(args: Array<String>) { runApplication<ResolveDependencyApplication>(*args) }
sealed class SubscriptionPatch {
abstract fun patch()
}
sealed class SubscriptionMondayPatch : SubscriptionPatch() {
override fun patch() = println("Monday")
}
sealed class SubscriptionSundayPatch : SubscriptionPatch() {
override fun patch() = println("Sunday")
}
fun interface SubscriptionService<T : SubscriptionPatch> {
suspend fun apply(patch: T)
}
@Service
class CreateMondaySubscriptionService : SubscriptionService<SubscriptionMondayPatch> {
override suspend fun apply(patch: SubscriptionMondayPatch) = patch.patch()
}
@Service
class CreateSundaySubscriptionService : SubscriptionService<SubscriptionSundayPatch> {
override suspend fun apply(patch: SubscriptionSundayPatch) = patch.patch()
}
@Service
class UpdateSubscriptionUseCase {
@Autowired
private lateinit var services: List<SubscriptionService<out SubscriptionPatch>>
@PostConstruct
suspend fun postContruct() = services.map { it.apply(CreateMondaySubscriptionService()) }
}
I used some approaches, but using the operator out
is the best approach actually, because I can’t change the code base.
I tried to use when
checking the type in each service, tried to use forced cast, but none work because the out
rewrite the base type.