เหตุใดเราจึงใช้“ วัตถุที่เป็นคู่หู” แทนชนิดของเขตข้อมูลคง Java ใน Kotlin


145

ความหมายที่ตั้งใจไว้ของ "วัตถุร่วม" คืออะไร? จนถึงตอนนี้ฉันได้ใช้มันเพื่อแทนที่ Java staticเมื่อฉันต้องการมัน

ฉันสับสนกับ:

  • ทำไมถึงเรียกว่า "สหาย"
  • การสร้างคุณสมบัติสแตติกหลายอันหมายความว่าฉันต้องรวมกลุ่มเข้าด้วยกันในcompanion objectบล็อกหรือไม่
  • เมื่อต้องการสร้างอินสแตนซ์ซิงเกิลที่กำหนดขอบเขตไว้กับชั้นเรียนฉันมักจะเขียน

:

companion object {
    val singleton by lazy { ... }
}

ซึ่งดูเหมือนว่าเป็นวิธีการที่ไม่มีความหมายในการทำ วิธีที่ดีกว่าคืออะไร

คำตอบ:


108
  • ความหมายที่ตั้งใจไว้ของ "วัตถุร่วม" คืออะไร? ทำไมถึงเรียกว่า "สหาย"

    ครั้งแรก Kotlin ไม่ได้ใช้แนวคิดของ Java staticสมาชิกเพราะ Kotlin มีของตัวเองแนวคิดของobjectsสำหรับการอธิบายคุณสมบัติและฟังก์ชั่นการเชื่อมต่อกับรัฐเดี่ยวและ Java staticเป็นส่วนหนึ่งของชั้นเรียนสามารถแสดงออกอย่างหรูหราในแง่ของการเดี่ยว: มันเป็นวัตถุเดี่ยวว่า สามารถเรียกโดยใช้ชื่อคลาส ดังนั้นการตั้งชื่อ: มันเป็นวัตถุที่มาพร้อมกับชั้นเรียน

    ชื่อของมันเคยเป็นclass objectและdefault objectแต่แล้วมันก็เปลี่ยนชื่อcompanion objectซึ่งเป็นที่ชัดเจนมากขึ้นและยังมีความสอดคล้องกับสกาล่าวัตถุสหาย

    นอกเหนือจากการตั้งชื่อแล้วมันมีประสิทธิภาพมากกว่าstaticสมาชิกของJava : มันสามารถขยายคลาสและอินเทอร์เฟซและคุณสามารถอ้างอิงและส่งผ่านเช่นเดียวกับวัตถุอื่น ๆ

  • การสร้างคุณสมบัติสแตติกหลายอันหมายความว่าฉันต้องรวมกลุ่มเข้าด้วยกันในcompanion objectบล็อกหรือไม่

    ใช่นั่นเป็นวิธีที่ใช้สำนวน หรือคุณสามารถจัดกลุ่มพวกเขาในวัตถุที่ไม่ใช่คู่หูตามความหมายของมัน:

    class MyClass {
        object IO {
            fun makeSomethingWithIO() { /* ... */ }
        }
    
        object Factory {
            fun createSomething() { /* ... */ }
        }
    }
  • ในการสร้างอินสแตนซ์ซิงเกิลที่ถูกกำหนดขอบเขตไว้ในชั้นเรียนฉันมักจะเขียน/*...*/สิ่งที่ดูเหมือนเป็นวิธีที่ไม่มีความคิด วิธีที่ดีกว่าคืออะไร

    ขึ้นอยู่กับสิ่งที่คุณต้องการในแต่ละกรณี รหัสของคุณเหมาะสมกับการจัดเก็บสถานะที่ถูกผูกไว้กับคลาสซึ่งเริ่มต้นเมื่อมีการเรียกครั้งแรก

    หากคุณไม่ต้องการเชื่อมต่อกับคลาสให้ใช้การประกาศวัตถุ:

    object Foo {
        val something by lazy { ... }
    }

    คุณยังสามารถลบการlazy { ... }มอบหมายเพื่อให้คุณสมบัติเริ่มต้นกับการใช้งานของคลาสเช่นเดียวกับ Java static initializers

    นอกจากนี้คุณยังอาจพบวิธีที่มีประโยชน์ของการเริ่มต้นของรัฐเดี่ยว


ตัวอย่างที่ดีและเป็นสำนวน
Trein

19

ทำไมถึงเรียกว่า "สหาย"

วัตถุนี้เป็นสหายของอินสแตนซ์ IIRC มีการอภิปรายกันอย่างยาวนานที่นี่: การเปลี่ยนแปลงของคลาสวัตถุใหม่

การสร้างคุณสมบัติสแตติกหลายรายการหมายความว่าฉันต้องรวมกลุ่มเข้าด้วยกันในบล็อกวัตถุที่แสดงร่วมกันหรือไม่

ใช่. คุณสมบัติ / วิธีการ "คงที่" ทุกรายการจะต้องอยู่ภายในสหายนี้

เมื่อต้องการสร้างอินสแตนซ์ซิงเกิลที่กำหนดขอบเขตไว้กับชั้นเรียนฉันมักจะเขียน

คุณไม่ได้สร้างอินสแตนซ์ซิงเกิลทันที มันถูกสร้างขึ้นเมื่อเข้าถึงsingletonเป็นครั้งแรก

ซึ่งดูเหมือนว่าเป็นวิธีการที่ไม่มีความหมายในการทำ วิธีที่ดีกว่าคืออะไร

ค่อนข้างไปกับobject Singleton { }การกำหนดชั้นเดียว ดู: การประกาศวัตถุ คุณไม่จำเป็นต้องสร้างอินสแตนซ์Singletonเพียงใช้อย่างนั้นSingleton.doWork()

เพียงจำไว้ว่า Kotlin เสนอสิ่งอื่น ๆ เพื่อจัดระเบียบรหัสของคุณ ขณะนี้มีทางเลือกให้กับฟังก์ชั่นแบบคงที่อย่างง่ายเช่นคุณสามารถใช้ฟังก์ชั่นระดับบนสุดแทน


7

ทำไมถึงเรียกว่า "สหาย"

การประกาศวัตถุภายในชั้นเรียนสามารถทำเครื่องหมายด้วยคำหลักสหาย:

class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}

สมาชิกของวัตถุที่แสดงร่วมสามารถเรียกได้โดยใช้ชื่อคลาสเป็นตัวระบุ:

val instance = MyClass.create()

หากคุณใช้ 'วัตถุ' โดยไม่มี 'เพื่อน' คุณต้องทำดังนี้:

val instance = MyClass.Factory.create()

ในความเข้าใจของฉัน 'เพื่อน' หมายถึงวัตถุนี้เป็นเพื่อนกับชั้นนอก


"object" ที่ไม่มี "สหาย" ถูกเรียกเช่นนี้ (MyClass (). create ()) เช่นเดียวกับซิงเกิลตัน แต่ในการเข้าถึงออบเจ็กต์เดี่ยวคุณต้องเริ่มต้นคลาส "outer" ก่อน
LiTTle

0

เราสามารถพูดได้ว่าสหายเหมือนกันกับ "บล็อกคงที่" เช่น Java แต่ในกรณีของ Kotlin ไม่มีแนวคิดบล็อกคงที่กว่าสหายเข้ามาในกรอบ

วิธีกำหนดบล็อกที่แสดงร่วม:

class Example {
      companion object {
        fun display(){
        //place your code
     }
  }
}

วิธีการโทรของบล็อกเพื่อนตรงกับชื่อคลาส

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