簡體   English   中英

如何在 Kotlin Android 中為數據類創建空構造函數

[英]How to create empty constructor for data class in Kotlin Android

我在 Kotlin 數據類中聲明了 10 多個變量,我想為它創建一個空的構造函數,就像我們通常在 Java 中所做的那樣。

數據類:

data class Activity(
    var updated_on: String,
    var tags: List<String>,
    var description: String,
    var user_id: List<Int>,
    var status_id: Int,
    var title: String,
    var created_at: String,
    var data: HashMap<*, *>,
    var id: Int,
    var counts: LinkedTreeMap<*, *>,
)

預期用途:

val activity =  Activity();
activity.title = "New Computer"
sendToServer(activity)

但是數據類要求在創建構造函數時傳遞所有參數。 我們如何像 Java POJO 類構造函數一樣簡化它?

val activity =  Activity(null,null,null,null,null,"New Computer",null,null,null,null)
sendToServer(activity)

您在這里有 2 個選擇:

  1. 為每個主要構造函數參數分配一個默認值:

     data class Activity( var updated_on: String = "", var tags: List<String> = emptyList(), var description: String = "", var user_id: List<Int> = emptyList(), var status_id: Int = -1, var title: String = "", var created_at: String = "", var data: HashMap<*, *> = hashMapOf<Any, Any>(), var id: Int = -1, var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>() )
  2. 聲明一個沒有參數的二級構造函數:

     data class Activity( var updated_on: String, var tags: List<String>, var description: String, var user_id: List<Int>, var status_id: Int, var title: String, var created_at: String, var data: HashMap<*, *>, var id: Int, var counts: LinkedTreeMap<*, *> ) { constructor() : this("", emptyList(), "", emptyList(), -1, "", "", hashMapOf<Any, Any>(), -1, LinkedTreeMap<Any, Any>() ) }

如果您不依賴Activity類的copyequals ,或者根本不使用自動生成的data class方法,則可以使用常規類,如下所示:

class ActivityDto {
    var updated_on: String = "",
    var tags: List<String> = emptyList(),
    var description: String = "",
    var user_id: List<Int> = emptyList(),
    var status_id: Int = -1,
    var title: String = "",
    var created_at: String = "",
    var data: HashMap<*, *> = hashMapOf<Any, Any>(),
    var id: Int = -1,
    var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
}

並非每個DTO 都需要是data class ,反之亦然。 事實上,根據我的經驗,我發現數據類在涉及一些復雜業務邏輯的領域特別有用。

如果您為所有字段提供默認值- Kotlin 會自動生成空構造函數。

data class User(var id: Long = -1,
                var uniqueIdentifier: String? = null)

你可以簡單地調用:

val user = User()

隨着@miensol 的回答,讓我補充一些細節:

如果您想要使用數據類的 Java 可見的空構造函數,則需要明確定義它。

使用默認值 + 構造函數說明符非常簡單:

data class Activity(
    var updated_on: String = "",
    var tags: List<String> = emptyList(),
    var description: String = "",
    var user_id: List<Int> = emptyList(),
    var status_id: Int = -1,
    var title: String = "",
    var created_at: String = "",
    var data: HashMap<*, *> = hashMapOf<Any, Any>(),
    var id: Int = -1,
    var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
) {
    constructor() : this(title = "") // this constructor is an explicit
                                     // "empty" constructor, as seen by Java.
}

這意味着通過這個技巧,您現在可以使用標准 Java 序列化程序(Jackson、Gson 等)序列化/反序列化這個對象。

對此的現代答案應該是使用 Kotlin 的no-arg compiler plugin ,它為經典猿創建了一個非參數構造代碼,更多關於這里

只需在 build.gradle 項目級別添加插件類路徑

    dependencies {
    ....

    classpath "org.jetbrains.kotlin:kotlin-noarg:1.4.10"

    ....
    }

然后配置您的注釋以生成no-arg構造函數

apply plugin: "kotlin-noarg"

noArg {
      annotation("your.path.to.annotaion.NoArg")
      invokeInitializers = true
}

然后定義您的注釋文件NoArg.kt

 @Target(AnnotationTarget.CLASS)
 @Retention(AnnotationRetention.SOURCE)
 annotation class NoArg

最后在任何數據類中,您都可以簡單地使用自己的注釋

@NoArg
data class SomeClass( val datafield:Type , ...   )

我曾經創建我自己的no-arg構造函數作為接受的答案,這是我通過搜索得到的,但后來這個插件發布了,我發現它更干凈了。

如果為每個主構造函數參數提供默認值:

data class Item(var id: String = "",
            var title: String = "",
            var condition: String = "",
            var price: String = "",
            var categoryId: String = "",
            var make: String = "",
            var model: String = "",
            var year: String = "",
            var bodyStyle: String = "",
            var detail: String = "",
            var latitude: Double = 0.0,
            var longitude: Double = 0.0,
            var listImages: List<String> = emptyList(),
            var idSeller: String = "")

並且從您可以在不帶參數的情況下調用它的實例的類中或使用您當時擁有的參數調用它

var newItem = Item()

var newItem2 = Item(title = "exampleTitle",
            condition = "exampleCondition",
            price = "examplePrice",
            categoryId = "exampleCategoryId")

文檔

注意:在 JVM 上,如果主構造函數的所有參數都有默認值,編譯器將生成一個額外的無參數構造函數,它將使用默認值。 這使得將 Kotlin 與通過無參數構造函數創建類實例的庫(例如 Jackson 或 JPA)一起使用變得更加容易。

我建議修改主構造函數並為每個參數添加一個默認值

data class Activity(
    var updated_on: String = "",
    var tags: List<String> = emptyList(),
    var description: String = "",
    var user_id: List<Int> = emptyList(),
    var status_id: Int = -1,
    var title: String = "",
    var created_at: String = "",
    var data: HashMap<*, *> = hashMapOf<Any, Any>(),
    var id: Int = -1,
    var counts: LinkedTreeMap<*, *> = LinkedTreeMap<Any, Any>()
)

您還可以通過添加? 然后你可以賦值null

data class Activity(
    var updated_on: String? = null,
    var tags: List<String>? = null,
    var description: String? = null,
    var user_id: List<Int>? = null,
    var status_id: Int? = null,
    var title: String? = null,
    var created_at: String? = null,
    var data: HashMap<*, *>? = null,
    var id: Int? = null,
    var counts: LinkedTreeMap<*, *>? = null
)

一般來說,避免可空對象是一個很好的做法——以我們不需要使用它們的方式編寫代碼。 與 Java 相比,不可為空的對象是 Kotlin 的優勢之一。 因此,上面的第一個選項是可取的

這兩個選項都會給你想要的結果:

val activity = Activity()
activity.title = "New Computer"
sendToServer(activity)

Kotlin 中數據類的非空輔助構造函數:

data class ChemicalElement(var name: String,
                           var symbol: String,
                           var atomicNumber: Int,
                           var atomicWeight: Double,
                           var nobleMetal: Boolean?) {

    constructor(): this("Silver",
                        "Ag", 
                        47,
                        107.8682,
                        true)
}

fun main() {
    var chemicalElement = ChemicalElement()
    println("RESULT: ${chemicalElement.symbol} means ${chemicalElement.name}")
    println(chemicalElement)
}

// RESULT: Ag means Silver
// ChemicalElement(name=Silver, symbol=Ag, atomicNumber=47, atomicWeight=107.8682, nobleMetal=true)

Kotlin 中數據類的空輔助構造函數:

data class ChemicalElement(var name: String,
                           var symbol: String,
                           var atomicNumber: Int,
                           var atomicWeight: Double,
                           var nobleMetal: Boolean?) {

    constructor(): this("",
                        "", 
                        -1,
                        0.0,
                        null)
}

fun main() {
    var chemicalElement = ChemicalElement()
    println(chemicalElement)
}

// ChemicalElement(name=, symbol=, atomicNumber=-1, atomicWeight=0.0, nobleMetal=null)

暫無
暫無

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

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