2016-10-19 71 views
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 ?: "") 
         } 
        } 
       } 
      } 
     } 
    } 
} 

回答

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:編譯器分析控制流並證明如果最後一條語句是reac hed然後沒有上面檢查的值是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 s):

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 ?: "") 
} 
+4

哇......我剛纔意識到,如果你不想要它們,甚至可以內聯所有這些局部變量。例如'... return AnswerResponseUi(userAnswer.id?:return null,answerResponse.answer?.id?:return null,...' – mfulton26

+0

可讀性是關鍵,所以不要嘗試內聯所有內容;)但這確實令人印象深刻! – voddan

相關問題