0Pricing
Kotlin Academy · บทเรียน

แนวปฏิบัติที่ดี

ทำให้ตัวดำเนินการมีความหมายที่เข้าใจง่าย

แนวปฏิบัติที่ดี เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

รักษาความเป็นธรรมชาติของตัวดำเนินการ

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

data class Vec(val x: Int, val y: Int) {
    operator fun plus(o: Vec) = Vec(x + o.x, y + o.y)
}

fun main() {
    println(Vec(1, 2) + Vec(3, 4))
}

รักษาความหมายที่คาดหวัง

ยึดหลักพีชคณิตตามปกติ: a + b ควรให้ความรู้สึกว่าสลับที่ได้สำหรับชนิดข้อมูลที่สมมาตร และไม่ควรทำให้ผู้อ่านประหลาดใจ

data class Money(val cents: Int) {
    operator fun plus(o: Money) = Money(cents + o.cents)
}

fun main() {
    println(Money(100) + Money(50))
}

ควรเลือกใช้ความไม่เปลี่ยนรูป

ตัวดำเนินการอย่าง plus ควรส่งคืนค่าใหม่แทนการเปลี่ยนแปลงตัวรับ ซึ่งสอดคล้องกับพฤติกรรมของตัวเลข

data class Point(val x: Int) {
    operator fun plus(o: Point) = Point(x + o.x)
}

fun main() {
    val a = Point(1)
    val b = a + Point(2)
    println("${a.x} ${b.x}")
}

plus กับ plusAssign

กำหนด plus สำหรับค่าที่ไม่เปลี่ยนรูป และกำหนด plusAssign สำหรับการเปลี่ยนแปลงคอนเทนเนอร์แบบแก้ไขภายในตำแหน่งเดิม หลีกเลี่ยงการกำหนดทั้งสองแบบให้มีพฤติกรรมขัดแย้งกัน

class Cart {
    val items = mutableListOf<String>()
    operator fun plusAssign(item: String) { items.add(item) }
}

fun main() {
    val c = Cart()
    c += "book"
    println(c.items)
}

ให้ชนิดที่ส่งคืนสอดคล้องกัน

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

data class N(val v: Int) {
    operator fun plus(o: N) = N(v + o.v)
}

fun main() {
    println((N(1) + N(2) + N(3)).v)
}

อย่าโอเวอร์โหลดเพียงเพื่อความซับซ้อน

หากฟังก์ชันที่มีชื่ออ่านเข้าใจได้ดีกว่า ก็ควรใช้ฟังก์ชันนั้น ตัวดำเนินการเหมาะสำหรับความหมายที่เกี่ยวกับตัวเลขหรือคอนเทนเนอร์อย่างแท้จริง ไม่ใช่สำหรับปริศนา

data class Log(val lines: List<String>) {
    fun append(line: String) = Log(lines + line)
}

fun main() {
    println(Log(emptyList()).append("start").lines)
}

รักษาความสอดคล้องของ equals และ hashCode

หากคุณโอเวอร์โหลดการเปรียบเทียบหรือความเท่ากัน ต้องรักษา equals และ hashCode ให้สอดคล้องกัน เพื่อป้องกันไม่ให้คอลเลกชันทำงานผิดพลาด

data class Id(val v: Int)

fun main() {
    val set = hashSetOf(Id(1), Id(1))
    println(set.size)
}

ระวังลำดับความสำคัญของตัวดำเนินการ

ตัวดำเนินการที่โอเวอร์โหลดยังคงใช้ลำดับความสำคัญแบบเดียวกับตัวดำเนินการในตัว ออกแบบให้ลำดับความสำคัญตามธรรมชาติสร้างผลลัพธ์ที่คาดหวัง

data class N(val v: Int) {
    operator fun plus(o: N) = N(v + o.v)
    operator fun times(o: N) = N(v * o.v)
}

fun main() {
    println((N(2) + N(3) * N(4)).v)
}

จัดทำเอกสารสำหรับตัวดำเนินการที่คาดเดาได้ยาก

หากตัวดำเนินการทำสิ่งที่ไม่ชัดเจน ควรเพิ่มความคิดเห็นหรือเอกสารประกอบ เพื่อไม่ให้ผู้เรียกใช้เข้าใจผิด

data class Range2(val start: Int, val end: Int) {
    // contains: is value inside the range?
    operator fun contains(v: Int) = v in start..end
}

fun main() {
    println(5 in Range2(1, 10))
}

ใช้ contains สำหรับ in

ตัวดำเนินการ in จะจับคู่กับ contains โอเวอร์โหลดตัวดำเนินการนี้เฉพาะเมื่อสามารถนิยามการเป็นสมาชิกสำหรับชนิดข้อมูลของคุณได้อย่างชัดเจน

class Team(val members: List<String>) {
    operator fun contains(name: String) = name in members
}

fun main() {
    val t = Team(listOf("Ann", "Bo"))
    println("Ann" in t)
}

หากไม่แน่ใจ ให้ใช้ฟังก์ชัน

เมธอดที่มีชื่อสื่อความหมายชัดเจนมักปลอดภัยกว่าตัวดำเนินการที่เข้าใจได้ยาก ใช้การโอเวอร์โหลดเฉพาะเมื่อช่วยให้อ่านโค้ดได้ดีขึ้นอย่างแท้จริง

data class Temperature(val c: Int) {
    fun warmerThan(o: Temperature) = c > o.c
}

fun main() {
    println(Temperature(30).warmerThan(Temperature(20)))
}

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจเกี่ยวกับแนวปฏิบัติที่ดีในการโอเวอร์โหลดตัวดำเนินการ

สรุปทบทวน

คุณได้เรียนรู้แนวปฏิบัติที่ดีในการโอเวอร์โหลดตัวดำเนินการ:

  • โอเวอร์โหลดเฉพาะเมื่อความหมายชัดเจนและเป็นไปตามธรรมเนียม
  • ควรเลือกใช้ค่าที่ไม่เปลี่ยนรูปและส่งคืนชนิดเดียวกัน เพื่อให้เชื่อมผลลัพธ์ต่อกันได้
  • แยก plus ซึ่งทำงานกับค่า ออกจาก plusAssign ซึ่งใช้เปลี่ยนแปลงค่า
  • รักษา equals/hashCode ให้สอดคล้องกัน และเลือกใช้ฟังก์ชันที่มีชื่อเมื่ออ่านเข้าใจได้ชัดเจนกว่า
data class V(val x: Int) {
    operator fun plus(o: V) = V(x + o.x)
}

fun main() {
    println((V(2) + V(5)).x)
}

คำถามที่พบบ่อย

บทเรียน “แนวปฏิบัติที่ดี” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “แนวปฏิบัติที่ดี” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “แนวปฏิบัติที่ดี”

ทำให้ตัวดำเนินการมีความหมายที่เข้าใจง่าย คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่

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

บทเรียน “แนวปฏิบัติที่ดี” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม

ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ฟังก์ชันตัวดำเนินการ
  2. ตัวดำเนินการเปรียบเทียบ
  3. ดัชนีและการเรียกใช้งาน
  4. แนวปฏิบัติที่ดี
← กลับไปที่ Kotlin Academy