我有一个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 ?: "")
}
}
}
}
}
}
}
答案 0 :(得分:4)
如果您的课程AnswerGson
和AnswerResponseGson
将其属性声明为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 ?: "")
}