Как создать пустой конструктор для класса данных в Kotlin Android
У меня есть параметр 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)
Ответы
Ответ 1
У вас есть 2 варианта:
-
Назначьте значение по умолчанию для каждого параметра primary constructor:
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>()
)
-
Объявить вторичный конструктор, который не имеет параметров:
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>()
)
}
Если вы не полагаетесь на copy
или equals
класса 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 должен быть data class
и наоборот. Фактически, по моему опыту, я считаю, что классы данных особенно полезны в областях, которые связаны с некоторой сложной бизнес-логикой.
Ответ 2
Если вы задаете значения по умолчанию для всех полей - Kotlin автоматически генерирует пустой конструктор.
data class User(var id: Long = -1,
var uniqueIdentifier: String? = null)
и вы можете просто позвонить:
val user = User()
Ответ 3
Наряду с ответом @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 и т.д.).
Ответ 4
Если вы зададите значение по умолчанию для каждого параметра основного конструктора:
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")
Ответ 5
Непустой вторичный конструктор для класса данных в Котлине:
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)
Пустой вторичный конструктор для класса данных в Котлине:
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)
Ответ 6
Я бы предложил изменить основной конструктор и добавить значение по умолчанию для каждого параметра:
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
)
Вообще, хорошей практикой является избегать объектов, которые могут быть обнуляемыми - пишите код так, чтобы нам не нужно было его использовать. Не допускающие обнуления объекты являются одним из преимуществ Kotlin по сравнению с Java. Поэтому первый вариант выше предпочтителен.
Оба варианта дадут вам желаемый результат:
val activity = Activity()
activity.title = "New Computer"
sendToServer(activity)
Ответ 7
Из документации
ПРИМЕЧАНИЕ. Если в JVM все параметры первичного конструктора имеют значения по умолчанию, компилятор сгенерирует дополнительный конструктор без параметров, который будет использовать значения по умолчанию. Это облегчает использование Kotlin с такими библиотеками, как Jackson или JPA, которые создают экземпляры классов с помощью конструкторов без параметров.