[英]Data class being used by other classes as parameter
我想使用數據類來存儲用戶輸入和計算結果。 然后將數據類轉換為實體並更新數據庫。
問題是我不清楚使用數據類的最佳實踐。
我已閱讀文檔: https ://kotlinlang.org/docs/data-classes.html 以及其他來源。 但是,他們沒有更復雜的示例來說明不同的類應該如何訪問和操作數據。
我正在用 Kotlin 編寫一個計算立方體的體積和平方英尺的 android 應用程序。 它從數據庫中檢索最后一個多維數據集並打印結果。 然后它詢問用戶立方體的長度。 它計算並打印輸入的體積、平方英尺和立方體長度。 然后它將結果上傳到數據庫並重復,直到用戶退出。 為簡單起見,數據庫僅存儲一個多維數據集。
我附上了一個代碼示例並有疑問:
1.我的示例是如何使用數據類的最佳實踐。
2.如果我在類 SquareFeetFormula() 中使用數據類作為參數,則 main 中的數據類將更改 testData 的值。 最好使用 .copy() 來避免對原始數據進行看不見的更改。
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:
val
而不是var
。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)
玩得開心編碼。
我對你的問題的看法
通常在 Kotlin 中我們使用數據類來表示數據結構(即只攜帶數據但沒有行為)。 在您的示例中, CubeInput
和CubeResult
是一種數據傳輸對象,它們很好地說明了使用數據類。
這更多的是關於應用程序設計。 通常我們更喜歡不可變對象而不是可變對象,並且 Kotlin 通過val
和var
關鍵字處理可變性。 @Elek 已經為如何更改代碼提供了很好的說明。
無論您使用class
還是data class
,您都將面臨同樣的問題。
關於lateinit var
的另一件事。
在編寫 Kotlin 時,我們希望謹慎使用lateinit var
,因為它可以使我們的代碼不為 null 安全(這是 Kotlin 提供的好處之一)。 如果您的代碼的用戶忘記調用setInput
,則會引發空指針異常。
這可以通過將代碼更改為來避免
calculate(input: CubeInput)
class SquareFeetFormula(private val input: CubeInput){
fun calculate () : Double {
return input.copy(
// logic here
)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.