Kotlin Android'de veri sınıfı için boş oluşturucu nasıl oluşturulur


195

Bir veri sınıfında 10 + parametre var, boş bir yapıcı ile veri sınıfını başlatmak ve setter kullanarak yalnızca birkaç parametre için değerleri ayarlamak ve nesneyi sunucuya geçmek istiyorum.

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

Kullanımı:

Böyle bir şey kolay olacak

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

Ancak, oluşturucu oluşturulurken tüm argümanların iletilmesini gerektirir. Yukarıdaki gibi nasıl basitleştirebilirim?

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

Yanıtlar:


246

Burada 2 seçeneğiniz var:

  1. Her birincil kurucu parametresine varsayılan bir değer atayın :

    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. Parametresi olmayan ikincil bir kurucu bildiriniz :

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

İtimat yoksa copyya equalsait Activitysınıf veya otomatik olarak oluşturulan kullanmayan data classhiç yöntemleri bu kadar gibi düzenli sınıfını kullanabilirsiniz:

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

Her DTO'nun a data classve tersi olması gerekmez . Aslında tecrübelerime göre, veri sınıflarının bazı karmaşık iş mantığını içeren alanlarda özellikle yararlı olduğunu düşünüyorum.


1
Teşekkürler @miensol, Bu kopya eğlenceli kullanılarak yapılabilir herhangi bir yolu var mı. Örneğin. kotlinlang.org/docs/reference/data-classes.html#copying
Sai

@SaiKiran kullanmak copyiçin bir veri sınıfı örneğine ihtiyacınız var. Bunu oluşturmak için bir kurucu çağırmanız gerekir - ve işte sorun buydu.
miensol

Android Studio 2.3 için Kotlin 1.1.2 kullanıyorum ve emptyList kullanılamıyor: /
Gonzalo

Boşver. Build.gradle config dosyama kotlin eklemedim.
Gonzalo

3
@Muhammadchhota emptyListtekrar tekrar bellek ayırmayacaktır. Tek bir ton döndürür .
miensol

71

Tüm alanlara varsayılan değerler verirseniz - boş yapıcı Kotlin tarafından otomatik olarak oluşturulur.

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

ve sadece şunu arayabilirsiniz:

val user = User()

1
id otomatik olarak oluşturulmuşsa nasıl kullanılır?
Siddhpura Amit

Benim için çalıştı. Firebase Sohbet mesajı için:class FeelComChatMessage (messageText: String = "", messageUser: String = "")
Jitendra Surve

14

@Miensol yanıtıyla birlikte, bazı ayrıntıları eklememe izin verin:

Veri sınıflarını kullanan Java tarafından görülebilir boş bir kurucu istiyorsanız, bunu açıkça tanımlamanız gerekir.

Varsayılan değerleri + yapıcı belirleyicisini kullanmak oldukça kolaydır:

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

Bu, bu hile ile artık bu nesneyi standart Java serileştiricileri (Jackson, Gson vb.) İle serileştirebilir / serisini kaldırabileceğiniz anlamına gelir.


Son övgü yanlış. En azından Gson serileştiricisi için, aslında, Gson nesneleri oluşturmak için güvensiz mekanizmayı kullanır ve kurucunuzu çağırmaz. Burada ilgili bir soruyu yeni yanıtladım stackoverflow.com/questions/59390294/…
Võ Quang Hòa

6

Her birincil kurucu parametresine varsayılan bir değer verirseniz:

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

ve örneklerin argüman olmadan veya o andaki argümanlarla arayabileceğiniz sınıftan

var newItem = Item()

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

3

Birincil yapıcıyı değiştirmenizi ve her parametreye varsayılan bir değer eklemenizi öneririm :

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

Ayrıca değerleri ekleyerek değerleri ?geçersiz hale getirebilir ve daha sonra şunları onaylayabilirsiniz 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
)

Genel olarak, null olabilecek nesnelerden kaçınmak iyi bir uygulamadır - kodu bunları kullanmamız gerekmediği şekilde yazın. Null olmayan nesneler, Java'ya kıyasla Kotlin'in avantajlarından biridir. Bu nedenle, yukarıdaki ilk seçenek tercih edilir .

Her iki seçenek de size istenen sonucu verecektir:

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

2

Kotlin'deki veri sınıfı için boş olmayan ikincil kurucu:

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'deki veri sınıfı için boş ikincil kurucu:

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

Gönderen dokümantasyon

NOT: JVM'de, birincil kurucunun tüm parametrelerinin varsayılan değerleri varsa, derleyici varsayılan değerleri kullanacak ek bir parametresiz kurucu oluşturur. Bu, Kotlin'i parametresiz kurucular aracılığıyla sınıf örnekleri yaratan Jackson veya JPA gibi kitaplıklarla kullanmayı kolaylaştırır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.