首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有泛型的Kotlin责任链模式

具有泛型的Kotlin责任链模式
EN

Stack Overflow用户
提问于 2018-09-24 20:43:25
回答 2查看 1.4K关注 0票数 4

使用责任链模式,我遇到了一个问题,期望下一个链式元素具有相同的第一个元素的泛型类型。我知道为什么会发生这种情况:第一个处理程序期望第二个处理程序使用泛型类型“”。我只是不知道该怎么解决。

关于如何使用handle it in java here,有一个答案,但是由于java没有具体化类型,所以在Kotlin中,这种方法看起来应该是不同的,对吗?

我想到了不同的选择:

  1. 不要使用泛型-会导致将集合类型转换为特定的子类型,而且看起来不干净。
  2. 尝试使用具体化类型(如何使用?)

为了说明这个问题,我在下面发布了一个演示代码。

代码语言:javascript
复制
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!!
    } 
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-24 21:16:54

Kotlin有一种叫做星体投影的东西也许能帮到你。它基本上告诉编译器,您并不真正关心您得到的ChainHandler类型。您可以使用它来编译setNextHandler,如下所示:

代码语言:javascript
复制
abstract class ChainHandler<T>{
  // Note the star projection here
  protected var nextHandlerInChain: ChainHandler<*>? = null

  // Defining a type parameter S, so that the return type is equal to the input type.
  fun <S> setNextHandler(handler: ChainHandler<S>): ChainHandler<S> {
    this.nextHandlerInChain = handler
    return handler
  }

  ...
}

你可以在这里读到更多关于恒星投影的信息:https://kotlinlang.org/docs/reference/generics.html#star-projections

至于类型参数的具体化:具体化的类型参数只适用于内联函数。不适用于类上的类型参数。

票数 6
EN

Stack Overflow用户

发布于 2018-09-24 21:17:02

这在很大程度上取决于希望处理程序如何交互的细节。对于这段代码,只需将下一个处理程序的类型(在var nextHandlerInChainfun setNextHandler中都更改为ChainHandler<*> )就可以了,因为process()无论如何都会返回与T无关的内容。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52487069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档