首页 > 解决方案 > 使用地图重构 kotlin 中的“何时”逻辑

问题描述

我目前正在重构一些 Kotlin 代码 - 我有一个很好的解决方案来进行简单的重构,但不确定如何在 Koltin 语法中使用映射来做到这一点。任何帮助都会很棒!

当前代码

这是我的数据类:

public sealed class DocumentBody {

    public data class Information(
        val Id: String,
        val name: String,
        val sort: Int = 2
    ) : DocumentBody ()

    public data class Location(
        val name: String,
        val address: String? = null,
        val sort: Int = 3
    ) : DocumentBody()

    public data class Rating(
        val name: String,
        val rating: Int,
        val sort: Int = 3
    ) : DocumentBody()
}

目前在我的代码库中有一个扩展函数,它可以根据上下文类型获取一些扩展信息,这是:

private fun DocumentBody.getExtendedInfo(
   settings: Settings = Settings()
): String? {
    return if (settings.versions != null) {
        when (this) {
            is DocumentBody.Information ->
                getExtentedInfo(ContentType.Information, settings.versions)
            is DocumentBody.Location ->
                getExtentedInfo(ContentType.Location, settings.versions)
            is DocumentBody.Rating ->
                getExtentedInfo(ContentType.Rating, settings.versions)
        }
    } else {
        when (this) {
            is DocumentBody.Information ->
                 ExtentedInfo[ContentType.Information]
            is DocumentBody.Location ->
                ExtentedInfo[ContentType.Location]
            is DocumentBody.Rating ->
                ExtentedInfo[ContentType.Rating]
        }
    }

重构代码

当寻找更好的方法来做到这一点时,我已经为 DocumentBody 类型创建了一个映射到 ContextType 像这样(不能为此在映射中设置类型 - 这可能是问题但不确定):

public val getContentTypeFromDocumentBody: Map<Any, ContentType> = mapOf(
    DocumentBody.Information to ContentType.Information,
    DocumentBody.Location to ContentType.Location,
    DocumentBody.Rating to ContentType.Rating
    )

在这里,我希望能够调用它并从键中获取 ContentType:

getContentTypeFromDocumentBody[docBodyType]

这目前正在通过数据,但我想要类型。我已经探索了如何用这样的想法来做到这一点:

    private fun DocumentBody.getExtendedInfo(settings: Settings = Settings()): String {
     getContentTypeFromDocumentBody.keys.map { docBodyType ->
                when (this) {
                    is docBodyType -> getContentTypeFromDocumentBody[docBodyType]
                    else -> error("invalid document type")
                }
            }
     }

但这不起作用,并且 creat 在第 4 行的 docBodyType 下有红线。

基本上我想将 DocumentBody 的类型传递到这个新地图中以获得内容类型,希望我想要做的这个想法是有意义的。任何帮助都会很棒!

标签: kotlin

解决方案


在我回答您的实际问题之前,我不得不说简单地将 ContentType 设为 DocumentBody 的属性会更直接,如下所示:

public sealed class DocumentBody(val contentType: ContentType) {

    public data class Information(
        val Id: String,
        val name: String,
        val sort: Int = 2
    ) : DocumentBody(ContentType.Information)

    public data class Location(
        val name: String,
        val address: String? = null,
        val sort: Int = 3
    ) : DocumentBody(ContentType.Location)

    public data class Rating(
        val name: String,
        val rating: Int,
        val sort: Int = 3
    ) : DocumentBody(ContentType.Rating)
}

我建议执行上述操作,但要回答您的问题,您不能简单地列出类名,就好像它们是某物的实例一样。您需要使用::class来获取要传递的实际对象:

public val getContentTypeFromDocumentBody: Map<KClass<out DocumentBody>, ContentType> = mapOf(
    DocumentBody.Information::class to ContentType.Information,
    DocumentBody.Location::class to ContentType.Location,
    DocumentBody.Rating::class to ContentType.Rating
)

然后使用::class您要与之比较的对象的 进行检查:

private fun DocumentBody.getExtendedInfo(settings: Settings = Settings()): String {
    val contentType = getContentTypeFromDocumentBody[this::class]
        ?: error("invalid document type")
    //...
}

我还建议给你的地图一个描述性的名称,而不是让它听起来像一个 getter 函数。类似的东西contentTypeByDocumentBodyClass


推荐阅读