วิธีสร้าง Constructor ว่างสำหรับคลาสข้อมูลใน Kotlin Android


195

ฉันมี 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)

คำตอบ:


245

คุณมี 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>()
                             )
    }

ถ้าคุณไม่ต้องพึ่งพาcopyหรือequalsของActivityชั้นเรียนหรือไม่ได้ใช้ autogenerated 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และในทางกลับกัน จากประสบการณ์ของฉันฉันพบว่าคลาสข้อมูลมีประโยชน์อย่างยิ่งในด้านที่เกี่ยวข้องกับตรรกะทางธุรกิจที่ซับซ้อน


1
ขอบคุณ @ miensol มีวิธีใดบ้างที่สามารถทำได้โดยใช้ความสนุกในการคัดลอก เช่น. kotlinlang.org/docs/reference/data-classes.html#copying
Sai

@SaiKiran ที่จะใช้copyคุณต้องการอินสแตนซ์ของคลาสข้อมูล ในการสร้างคุณจะต้องเรียกใช้ตัวสร้าง - และนี่คือปัญหา
miensol

ฉันใช้ Kotlin 1.1.2 สำหรับ Android Studio 2.3 และไม่มีรายการว่างเปล่า: /
กอนซาโล่

ไม่เป็นไร. ฉันไม่ได้เพิ่ม kotlin ในไฟล์ build.gradle config ของฉัน
กอนซาโล่

3
@Muhammadchhota emptyListจะไม่จัดสรรหน่วยความจำซ้ำ ๆ มันกลับเดี่ยว
miensol

70

หากคุณให้ค่าเริ่มต้นกับทุกฟิลด์ - ตัวสร้างที่ว่างเปล่าจะถูกสร้างขึ้นโดยอัตโนมัติโดย Kotlin

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

และคุณสามารถโทร:

val user = User()

1
ถ้า id ถูกสร้างขึ้นอัตโนมัติวิธีการใช้งาน?
Siddhpura Amit

ทำงานให้ฉัน สำหรับข้อความแชทของ Firebase:class FeelComChatMessage (messageText: String = "", messageUser: String = "")
Jitendra Surve

14

พร้อมด้วยคำตอบ @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 serializers (Jackson, Gson ฯลฯ )


การยกย่องครั้งสุดท้ายนั้นผิด อย่างน้อยสำหรับ Serializer Gson อันที่จริงแล้ว Gson ใช้กลไกที่ไม่ปลอดภัยในการสร้างวัตถุและมันจะไม่เรียกตัวสร้างของคุณ ฉันเพิ่งตอบคำถามที่เกี่ยวข้องที่นี่stackoverflow.com/questions/59390294/…
V

6

หากคุณให้ค่าเริ่มต้นกับพารามิเตอร์ตัวสร้างหลักแต่ละตัว:

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

3

ฉันขอแนะนำให้แก้ไขตัวสร้างหลักและเพิ่มค่าเริ่มต้นให้กับแต่ละพารามิเตอร์:

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

คุณสามารถทำให้ค่าเป็นโมฆะได้โดยการเพิ่ม?และจากนั้นคุณสามารถ 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
)

โดยทั่วไปแล้วมันเป็นวิธีปฏิบัติที่ดีในการหลีกเลี่ยงออบเจ็กต์ nullable - เขียนโค้ดในลักษณะที่เราไม่จำเป็นต้องใช้มัน วัตถุที่ไม่เป็นโมฆะเป็นข้อดีอย่างหนึ่งของ Kotlin เมื่อเทียบกับ Java ดังนั้นตัวเลือกแรกข้างต้นเป็นที่นิยม

ตัวเลือกทั้งสองจะให้ผลลัพธ์ที่คุณต้องการ:

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

2

คอนสตรัครองที่ไม่ว่างเปล่าสำหรับคลาสข้อมูลใน 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)

2

จากเอกสารประกอบ

หมายเหตุ: บน JVM หากพารามิเตอร์ทั้งหมดของตัวสร้างหลักมีค่าเริ่มต้นคอมไพเลอร์จะสร้างตัวสร้างแบบไม่มีพารามิเตอร์เพิ่มเติมซึ่งจะใช้ค่าเริ่มต้น สิ่งนี้ทำให้ง่ายต่อการใช้ Kotlin กับไลบรารีเช่น Jackson หรือ JPA ที่สร้างอินสแตนซ์ของคลาสผ่านตัวสร้างแบบไม่มีพารามิเตอร์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.