首页 文章

将具有可空字段的对象转换为具有非可空字段的对象或null

提问于
浏览
2

我有一个API返回的对象,它有不同的可空字段 . 我想创建一个具有非可空字段的另一个对象,或者如果不可能则返回null . 什么是最适合这种情况的语言习语?目前我正在使用 ?.let {} ,它看起来很难看:

fun convertAnswer(userAnswer: AnswerGson, answerResponse: AnswerResponseGson,
                  correctAnswerText: String): AnswerResponseUi? {
    return userAnswer.id?.let { userAnswerId ->
        userAnswer.text?.let { userAnswerText ->
            answerResponse.answer?.id?.let { correctAnswerId ->
                answerResponse.points?.let { points ->
                    answerResponse.discount?.let { discount ->
                        answerResponse.booster?.let { booster ->
                            return AnswerResponseUi(userAnswerId, correctAnswerId, userAnswerText,
                                    correctAnswerText, points, discount, booster.name ?: "")
                        }
                    }
                }
            }
        }
    }
}

1 回答

  • 4

    如果您的类 AnswerGsonAnswerResponseGson 将其属性声明为 val ,则可以将代码转换为如下所示:

    fun convertAnswer(userAnswer: AnswerGson, answerResponse: AnswerResponseGson,
                      correctAnswerText: String): AnswerResponseUi? {
        if (userAnswer.id == null ||
            userAnswer.text == null ||
            answerResponse.discount == null ||
            answerResponse.points == null ||
            answerResponse.booster == null ||
            answerResponse.answer == null ||
            answerResponse.answer.id == null
        ) return null
    
        return AnswerResponseUi(userAnswer.id, answerResponse.answer.id, userAnswer.text,
                                correctAnswerText, answerResponse.points,
                                answerResponse.discount, answerResponse.booster.name ?: "")
    }
    

    此示例使用smart casts:编译器分析控制流并证明如果到达最后一个语句,则上面检查的值都不是 null .

    这些检查不适用于安全的解除引用链,我必须首先检查 answerResponse.answer 然后才检查 answerResponse.answer.id .


    如果您有 var 属性,则无法应用智能强制转换,因为在检查后该值可能会更改 .

    在这种情况下,您仍然可以通过将值提取到局部变量并同时检查它们来减少代码中的嵌套:

    fun convertAnswer(userAnswer: AnswerGson, answerResponse: AnswerResponseGson,
                      correctAnswerText: String): AnswerResponseUi? {
        val answerId = userAnswer.id ?: return null
        val correctAnswerId = answerResponse.answer?.id ?: return null
        val userAnswerText = userAnswer.text ?: return null
        val points = answerResponse.points ?: return null
        val discount = answerResponse.discount ?: return null
        val booster = answerResponse.booster ?: return null
    
        return AnswerResponseUi(answerId, correctAnswerId, userAnswerText,
                                correctAnswerText, points,
                                discount, booster.name ?: "")
    }
    

    并且,正如@mfulton26注意到的,您甚至可以内联这些变量(也适用于 val ):

    fun convertAnswer(userAnswer: AnswerGson, answerResponse: AnswerResponseGson,
                      correctAnswerText: String): AnswerResponseUi? {
        return AnswerResponseUi(userAnswer.id ?: return null, 
                                answerResponse.answer?.id ?: return null, 
                                userAnswer.text ?: return null,
                                correctAnswerText, 
                                answerResponse.points ?: return null,
                                answerResponse.discount ?: return null, 
                                (answerResponse.booster ?: return null).name ?: "")
    }
    

相关问题