Используя шаблон цепочки ответственности, я столкнулся с проблемой, когда следующий элемент цепочки должен иметь тот же общий тип первого элемента.Я знаю , почему это происходит: первый обработчик ожидает, что второй обработчик будет использовать универсальный тип "Apple".Я просто не знаю точно, как это решить.
Существует ответ о том, как обработать это в Java, здесь , но поскольку в Java нет типов reified и все, что подход должен выглядеть по-другому в Kotlin, верно?
Существуют различные варианты, которые приходят мне в голову:
- Не использовать универсальные шаблоны - приведет к приведению типов коллекций к определенным подтипам и не будет выглядеть чисто
- Попробуйте использовать условные типы (как?)
Чтобы проиллюстрировать проблему, я выкладываю демонстрационный код ниже.
data class Apple(val name:String, val color:Int)
data class Orange(val circumference:Double)
object Main{
@JvmStatic
fun main(args: Array<String>) {
val first = FirstHandler()
val second = SecondHandler()
first.setNextHandler(second) // !!! wrong type here since <Apple> is expected
first.process()
}
}
abstract class ChainHandler<T>{
protected var nextHandlerInChain:ChainHandler<T>? = null
fun setNextHandler(handler: ChainHandler<T>): ChainHandler<T> {
this.nextHandlerInChain = handler
return handler
}
abstract fun peel(): Collection<T>
abstract fun process():MutableMap<String,Any> }
class FirstHandler : ChainHandler<Apple>() {
override fun peel(): Collection<Apple> {
return Collections.emptyList<Apple>()
}
override fun process(): MutableMap<String, Any> {
val peeledApples = peel()
val map = nextHandlerInChain?.process()
map?.put("apples",peeledApples) ?:kotlin.run {
val map = mutableMapOf<String,Any>()
map.put("apples",peeledApples)
}
return map!!
} }
class SecondHandler : ChainHandler<Orange>() {
override fun peel(): Collection<Orange> {
return Collections.emptyList<Orange>()
}
override fun process(): MutableMap<String, Any> {
val peeledOranges = peel()
val map = nextHandlerInChain?.process()
map?.put("oranges",peeledOranges) ?:kotlin.run {
val map = mutableMapOf<String,Any>()
map.put("oranges",peeledOranges)
}
return map!!
}
}