簡體   English   中英

其他類用作參數的數據類

[英]Data class being used by other classes as parameter

我想使用數據類來存儲用戶輸入和計算結果。 然后將數據類轉換為實體並更新數據庫。

問題是我不清楚使用數據類的最佳實踐。

我已閱讀文檔: https ://kotlinlang.org/docs/data-classes.html 以及其他來源。 但是,他們沒有更復雜的示例來說明不同的類應該如何訪問和操作數據。

我正在用 Kotlin 編寫一個計算立方體的體積和平方英尺的 android 應用程序。 它從數據庫中檢索最后一個多維數據集並打印結果。 然后它詢問用戶立方體的長度。 它計算並打印輸入的體積、平方英尺和立方體長度。 然后它將結果上傳到數據庫並重復,直到用戶退出。 為簡單起見,數據庫僅存儲一個多維數據集。

我附上了一個代碼示例並有疑問:

1.我的示例是如何使用數據類的最佳實踐。

2.如果我在類 SquareFeetFormula() 中使用數據類作為參數,則 main 中的數據類將更改 testData 的值。 最好使用 .copy() 來避免對原始數據進行看不見的更改。

  1. 如果我只使用一個類而不是一個數據類問題 2 就不會發生。
import kotlin.math.*
fun main() {
    val input = CubeInput("My Cube", 3.0, "Original text")
    val result = CubeResult(27.0, 54.0)
    val volume = VolumeFormula()
    val squareFeet = SquareFeetFormula()
    val printInfo = PrintInfo()
    val database = DatabaseOperations()

    database.getDatabase()

    println("Your database Cube was ")
    printInfo.print(input, result)


    while (true) {
        try {
            println("Start")
            println("Enter the new length or press any key to finish")
            val stringInput = readLine()!!
            input.length = stringInput.toDouble()

//          If I don't do .copy() testData in input changes from "Original text" to "I Changed"
            volume.setInput(input.copy())
            squareFeet.setInput(input.copy())

            result.volume = volume.calculate()
            result.squareFeet = squareFeet.calculate()
            printInfo.print(input, result)

            database.updateDatabase()

        } catch (e: Exception) {
            println("Done")
            break
        }
    }
}


data class CubeInput(var name : String, var length : Double, var testData: String)
data class CubeResult(var volume : Double, var squareFeet : Double)

class VolumeFormula(){
    private lateinit var input :CubeInput

    fun setInput (input1 : CubeInput){
        input=input1
    }
    fun calculate () : Double{
        return input.length.pow(3)
    }
}

class SquareFeetFormula(){
    private lateinit var input :CubeInput

    fun setInput (input1 : CubeInput){
        input=input1
    }
    fun calculate () : Double{
        input.testData="I changed"
        return input.length*input.length*6
    }
}

class PrintInfo() {
    fun print(input: CubeInput, result: CubeResult) {
        println(input.name + " has a length of "+ input.length + ", Width of "+result.volume+ ", and square feet of "+result.squareFeet)
        println("TestData: " +input.testData)
    }
}

class DatabaseOperations(){
    fun getDatabase() {
//        populate input data class and result data class from database
    }

    fun updateDatabase() {
//        convert input and result into Entity
//        update Entity in database
    }
}

謝謝

TL;TR:

  1. 最好在數據類中使用val而不是var
  2. 當您想要更改某些值時,請使用復制。
  3. 當您使用class而不是data class時,也會發生同樣的情況。 不可變的屬性( val )會阻止這種情況。

即使您使用class CubeInput而不是data class CubeInput ,您仍然可以更改SquareFeetFormula#calculate中的對象屬性,因為您通過引用傳遞對象( 這里解釋了按引用調用和按值調用之間的區別)。

您的數據類的實現和copy類型的使用取決於您的軟件設計。 在您的情況下,我會像這樣設計您的數據類:

// input parameter should be initialized and then be immutable
data class CubeInput(val name : String, val length : Double, val testData: String)

// once you calculated the result, its final, so immutable again
data class CubeResult(val volume : Double, val squareFeet : Double)

我通常將data class用於充當某種值容器的類。 這意味着,每當對象的某些值發生變化時,都會產生一個與原始對象不同的新對象。 因此我使用copy 例如

val input = CubeInput("Input", 1.0, "Start")
// damn i forget, that every input length should get an offset
val updatedInput = input.copy(length = input.length+2.0)

玩得開心編碼。

我對你的問題的看法

  1. 通常在 Kotlin 中我們使用數據類來表示數據結構(即只攜帶數據但沒有行為)。 在您的示例中, CubeInputCubeResult是一種數據傳輸對象,它們很好地說明了使用數據類。

  2. 這更多的是關於應用程序設計。 通常我們更喜歡不可變對象而不是可變對象,並且 Kotlin 通過valvar關鍵字處理可變性。 @Elek 已經為如何更改代碼提供了很好的說明。

  3. 無論您使用class還是data class ,您都將面臨同樣的問題。

關於lateinit var的另一件事。

在編寫 Kotlin 時,我們希望謹慎使用lateinit var ,因為它可以使我們的代碼不為 null 安全(這是 Kotlin 提供的好處之一)。 如果您的代碼的用戶忘記調用setInput ,則會引發空指針異常。

這可以通過將代碼更改為來避免

  1. 不是有狀態的,簡單的把輸入移到calculate方法中,即calculate(input: CubeInput)
  2. 構造公式時使輸入可用,即
class SquareFeetFormula(private val input: CubeInput){
    fun calculate () : Double {
        return input.copy(
           // logic here
        )
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM