繁体   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