So erstellen Sie einen leeren Konstruktor für die Datenklasse in Kotlin Android

190

Ich habe mehr als 10 Parameter in einer Datenklasse. Ich möchte die Datenklasse mit einem leeren Konstruktor initialisieren und die Werte nur für wenige Parameter mit dem Setter festlegen und das Objekt an den Server übergeben.

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<*, *>,
)

Verwendung:

So etwas wird einfach sein

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

Es müssen jedoch alle Argumente beim Erstellen des Konstruktors übergeben werden. Wie kann ich wie oben vereinfachen?

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

Antworten:

240

Sie haben hier 2 Möglichkeiten:

  1. Weisen Sie jedem primären Konstruktorparameter einen Standardwert zu :

    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. Deklarieren Sie einen sekundären Konstruktor ohne Parameter:

    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>()
                             )
    }

Wenn Sie sich nicht auf copyoder equalsvon der ActivityKlasse verlassen oder die automatisch data classgenerierten Methoden überhaupt nicht verwenden, können Sie die reguläre Klasse wie folgt verwenden:

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>()
}

Nicht jeder DTO muss ein sein data classund umgekehrt. Nach meiner Erfahrung sind Datenklassen in Bereichen mit komplexer Geschäftslogik besonders nützlich.

Miensol
quelle
1
Danke @miensol, gibt es eine Möglichkeit, dies mit Kopierspaß zu tun? z.B. kotlinlang.org/docs/reference/data-classes.html#copying
Sai
@SaiKiran zur Verwendung copybenötigen Sie eine Datenklasseninstanz. Um es zu erstellen, müssen Sie einen Konstruktor aufrufen - und hier war das Problem.
Miensol
Ich verwende Kotlin 1.1.2 für Android Studio 2.3 und emptyList ist nicht verfügbar: /
Gonzalo
Keine Ursache. Ich habe meiner Konfigurationsdatei build.gradle kein Kotlin hinzugefügt.
Gonzalo
3
@Muhammadchhota emptyListwird nicht wiederholt Speicher zuweisen.Es wird ein Singleton zurückgegeben .
Miensol
69

Wenn Sie allen Feldern Standardwerte zuweisen, wird der leere Konstruktor automatisch von Kotlin generiert.

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

und Sie können einfach anrufen:

val user = User()
kosiara - Bartosz Kosarzycki
quelle
Wenn die ID automatisch generiert wird, wie wird sie dann verwendet?
Siddhpura Amit
Hat für mich gearbeitet. Für Firebase Chat Nachricht:class FeelComChatMessage (messageText: String = "", messageUser: String = "")
Jitendra Surve
13

Lassen Sie mich zusammen mit der Antwort von @miensol einige Details hinzufügen:

Wenn Sie einen Java-sichtbaren leeren Konstruktor mit Datenklassen verwenden möchten, müssen Sie ihn explizit definieren.

Die Verwendung von Standardwerten + Konstruktorspezifizierer ist ganz einfach:

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.
}

Dies bedeutet, dass Sie mit diesem Trick dieses Objekt jetzt mit den Standard-Java-Serialisierern (Jackson, Gson usw.) serialisieren / deserialisieren können.

Gui13
quelle
Das letzte Lob ist falsch. Zumindest für den Gson-Serializer verwendet Gson den unsicheren Mechanismus zum Erstellen von Objekten und ruft Ihren Konstruktor nicht auf. Ich habe gerade eine verwandte Frage hier beantwortet stackoverflow.com/questions/59390294/…
Võ Quang Hòa
6

Wenn Sie jedem primären Konstruktorparameter einen Standardwert zuweisen:

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

und aus der Klasse, in der die Instanzen Sie ohne Argumente oder mit den Argumenten aufrufen können, die Sie in diesem Moment haben

var newItem = Item()

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

Ich würde vorschlagen, den primären Konstruktor zu ändern und jedem Parameter einen Standardwert hinzuzufügen :

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

Sie können Werte auch durch Hinzufügen auf ?Null setzen und dann Folgendes festlegen 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
)

Im Allgemeinen wird empfohlen, nullbare Objekte zu vermeiden. Schreiben Sie den Code so, dass wir sie nicht verwenden müssen. Nicht nullfähige Objekte sind einer der Vorteile von Kotlin gegenüber Java. Daher ist die erste Option oben vorzuziehen .

Mit beiden Optionen erhalten Sie das gewünschte Ergebnis:

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

Nicht leerer sekundärer Konstruktor für Datenklasse 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)

Leerer sekundärer Konstruktor für Datenklasse 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)
Andy Fedoroff
quelle
2

Aus der Dokumentation

ANMERKUNG: Wenn in der JVM alle Parameter des primären Konstruktors Standardwerte haben, generiert der Compiler einen zusätzlichen parameterlosen Konstruktor, der die Standardwerte verwendet. Dies erleichtert die Verwendung von Kotlin mit Bibliotheken wie Jackson oder JPA, die Klasseninstanzen über parameterlose Konstruktoren erstellen.

Gastón Saillén
quelle