I have two data class, and after I assign value to attribute in infoModel, I want assign them to infoArchiveModel which has the same fields, in this case, id, env, description and endpoint in infoArchiveModel should be same as those in infoModel , how can I do that?
data class infoModel(
#Id
val id: String = "",
val environment: String = "",
val description: String = "",
val endPoint: String = "",
)
data class infoArchiveModel(
#Id
val id: String = "",
val environment: String = "",
val description: String = "",
val endPoint: String = "",
val date: String = " "
)
A data class can also declare a secondary constructor, just like this:
data class infoArchiveModel(
#Id
val id: String = "",
val environment: String = "",
val description: String = "",
val endPoint: String = "",
val date: String = " "
) {
constructor(model: infoModel):
this (model.id, model.environment, model.description, model.endPoint)
}
//use this constructor
val model: infoModel = ...
val archiveModel = infoArchiveModel(model)
BTW, class names should always start with a capital case.
I have 10+ variables declared in Kotlin data class, and I would like to create an empty constructor for it like how we typically do in Java.
Data class:
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<*, *>,
)
Expected usage:
val activity = Activity();
activity.title = "New Computer"
sendToServer(activity)
But the data class requires all arguments to be passed while creating a constructor. How can we simplify this like the Java POJO class constructor?
val activity = Activity(null,null,null,null,null,"New Computer",null,null,null,null)
sendToServer(activity)
You have 2 options here:
Assign a default value to each primary constructor parameter:
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>()
)
Declare a secondary constructor that has no parameters:
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>()
)
}
If you don't rely on copy or equals of the Activity class or don't use the autogenerated data class methods at all you could use regular class like so:
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>()
}
Not every DTO needs to be a data class and vice versa. In fact in my experience I find data classes to be particularly useful in areas that involve some complex business logic.
If you give default values to all the fields - empty constructor is generated automatically by Kotlin.
data class User(var id: Long = -1,
var uniqueIdentifier: String? = null)
and you can simply call:
val user = User()
the modern answer for this should be using Kotlin's no-arg compiler plugin which creates a non argument construct code for classic apies more about here
simply you have to add the plugin class path in build.gradle project level
dependencies {
....
classpath "org.jetbrains.kotlin:kotlin-noarg:1.4.10"
....
}
then configure your annotation to generate the no-arg constructor
apply plugin: "kotlin-noarg"
noArg {
annotation("your.path.to.annotaion.NoArg")
invokeInitializers = true
}
then define your annotation file NoArg.kt
#Target(AnnotationTarget.CLASS)
#Retention(AnnotationRetention.SOURCE)
annotation class NoArg
finally in any data class you can simply use your own annotation
#NoArg
data class SomeClass( val datafield:Type , ... )
I used to create my own no-arg constructor as the accepted answer , which i got by search but then this plugin released or something and I found it way cleaner .
Along with #miensol answer, let me add some details:
If you want a Java-visible empty constructor using data classes, you need to define it explicitely.
Using default values + constructor specifier is quite easy:
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.
}
This means that with this trick you can now serialize/deserialize this object with the standard Java serializers (Jackson, Gson etc).
If you give a default value to each primary constructor parameter:
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 = "")
and from the class where the instances you can call it without arguments or with the arguments that you have that moment
var newItem = Item()
var newItem2 = Item(title = "exampleTitle",
condition = "exampleCondition",
price = "examplePrice",
categoryId = "exampleCategoryId")
Non-empty secondary constructor for data class in 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)
Empty secondary constructor for data class in 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)
From the documentation
NOTE: On the JVM, if all of the parameters of the primary constructor
have default values, the compiler will generate an additional
parameterless constructor which will use the default values. This
makes it easier to use Kotlin with libraries such as Jackson or JPA
that create class instances through parameterless constructors.
I'd suggest to modify the primary constructor and add a default value to each parameter:
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>()
)
You can also make values nullable by adding ? and then you can assing 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
)
In general, it is a good practice to avoid nullable objects - write the code in the way that we don't need to use them. Non-nullable objects are one of the advantages of Kotlin compared to Java. Therefore, the first option above is preferable.
Both options will give you the desired result:
val activity = Activity()
activity.title = "New Computer"
sendToServer(activity)
I have an object
class Person {
#JsonProperty("name")
var name: String? = null
#JsonProperty("id")
lateinit var id: String}
There is an only empty constructor and I want to create a person so I wrote:
val person = Person()
person.name = "someName"
person.id = "SomeId"
I'm pretty sure that there is a prettier syntax, something like
val person = Person {name = "someName" , id = "someId"}
but I can't find an example.
am I missing something? should I create a secondary constructor to use this syntax or is there another way?
Please check apply method.
Your code will be like this:
val person = Person().apply {name = "someName", id = "someId"}
Another way - you can change declaration of Person to (e.g. just change brackets, replace var to val and remove lateinit):
class Person (#JsonProperty("name") val name: String? = null,
#JsonProperty("id") val id: String )
Then you will able to do this:
val person = Person(name = "someName", id = "someId")
You can achieve it with the constructor parameter.
class Person(
#JsonProperty("name")
var name: String? = null,
#JsonProperty("id")
var id: String
)
val person = Person(name = "someName", id = "someId")
Another way is make your class and desired variables open to be overridden.
open class Person {
#JsonProperty("name")
open var name: String? = null
#JsonProperty("id")
open var id: String = ""
}
val person = object : Person() {
override var name: String? = "SomeName"
override var id = "SomeId"
}