如何在Kotlin Android中为数据类创建空的构造函数


194

我在一个数据类中有10个以上的参数,我想用一个空的构造函数初始化该数据类,并使用setter仅设置几个参数的值,然后将该对象传递给服务器。

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)

但这要求在创建构造函数时传递所有参数。我如何像上面那样简化?

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

Answers:


242

您在这里有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>()
                             )
    }
    

如果不依靠copyequals在的Activity阶级或不使用自动生成的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都需要成为a data class,反之亦然。实际上,根据我的经验,我发现数据类在涉及一些复杂业务逻辑的领域中特别有用。


1
感谢@miensol,有什么办法可以使用复制乐趣来做到这一点。例如。kotlinlang.org/docs/reference/data-classes.html#copying

@SaiKiran要使用copy您需要一个数据类实例。要创建它,您需要调用一个构造函数-这就是问题所在。
miensol

我将Kotlin 1.1.2用于Android Studio 2.3,并且emptyList不可用:/
Gonzalo

没关系。我没有将kotlin添加到我的build.gradle配置文件中。
贡萨洛

3
@Muhammadchhota emptyList不会重复分配内存。它返回一个单例
miensol

69

如果为所有字段提供默认值 -Kotlin将自动生成空构造函数。

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

您可以简单地致电:

val user = User()

如果id是自动生成的,该如何使用?
Siddhpura Amit

为我工作。对于Firebase聊天消息:class FeelComChatMessage (messageText: String = "", messageUser: String = "")
Jitendra Surve

13

除了@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等)对这个对象进行序列化/反序列化。


最后的建议是错误的。实际上,至少对于Gson序列化器而言,Gson使用了不安全的机制来创建对象,并且它不会调用构造函数。我刚才已经回答这里一个相关的问题stackoverflow.com/questions/59390294/...
VO广HOA

6

如果为每个主要构造函数参数提供默认值:

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")

3

我建议修改主构造函数并为每个参数添加一个默认值

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)

2

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)

2

文档中

注意:在JVM上,如果主构造函数的所有参数都具有缺省值,则编译器将生成一个将使用缺省值的附加无参数构造函数。这使得将Kotlin与通过无参数构造函数创建类实例的Jackson或JPA之类的库一起使用更加容易。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.