0Pricing
Scala for Backend Engineering & Functional Programming · บทเรียน

การแปลงโดยนัย

ใช้อย่างระมัดระวัง

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

การแปลงโดยนัยคืออะไร

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

object Main {
  import scala.language.implicitConversions
  implicit def intToString(x: Int): String = s"number-$x"
  def main(args: Array[String]): Unit = {
    val s: String = 42
    println(s)
  }
}

คอมไพเลอร์ใช้การแปลงเหล่านี้อย่างไร

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

object Main {
  import scala.language.implicitConversions
  implicit def doubleToInt(d: Double): Int = d.toInt
  def addTen(x: Int): Int = x + 10
  def main(args: Array[String]): Unit = {
    println(addTen(3.9))
  }
}

การเปิดใช้ความสามารถนี้

การกำหนดการแปลงโดยนัยจำเป็นต้องนำเข้า scala.language.implicitConversions มิฉะนั้นคอมไพเลอร์จะแจ้งคำเตือน นี่เป็นการเพิ่มข้อจำกัดโดยตั้งใจเพื่อไม่สนับสนุนการใช้มากเกินไป

object Main {
  import scala.language.implicitConversions
  case class Celsius(value: Double)
  implicit def doubleToCelsius(d: Double): Celsius = Celsius(d)
  def describe(c: Celsius): String = s"${c.value} C"
  def main(args: Array[String]): Unit = {
    println(describe(36.6))
  }
}

การห่อหุ้มเพื่อเพิ่มเมธอด (รูปแบบเดิม)

ก่อนมีเมธอดส่วนขยาย การแปลงโดยนัยเป็นวิธีเพิ่มเมธอดให้ชนิดที่มีอยู่แล้วผ่านคลาสห่อหุ้ม ซึ่งเรียกกันว่ารูปแบบปรับปรุงไลบรารีด้วยตนเอง

object Main {
  import scala.language.implicitConversions
  class RichInt2(x: Int) {
    def squared: Int = x * x
  }
  implicit def toRich(x: Int): RichInt2 = new RichInt2(x)
  def main(args: Array[String]): Unit = {
    println(5.squared)
  }
}

อันตราย: ความประหลาดใจที่เงียบงัน

เนื่องจากการแปลงมองไม่เห็น ณ จุดเรียกใช้ จึงอาจทำให้เกิดพฤติกรรมที่สับสนและข้อผิดพลาดที่ติดตามสาเหตุได้ยาก การพิมพ์ผิดอาจยังคอมไพล์ผ่านโดยบังเอิญกระตุ้นให้เกิดการแปลง

object Main {
  import scala.language.implicitConversions
  implicit def boolToInt(b: Boolean): Int = if (b) 1 else 0
  def main(args: Array[String]): Unit = {
    val total = true + 4 // surprising! becomes 1 + 4
    println(total)
  }
}

เลือกใช้การแปลงอย่างชัดเจน

บ่อยครั้งทางเลือกที่ปลอดภัยที่สุดคือใช้เมธอดที่มีชื่อชัดเจนแทนการแปลงโดยนัย โค้ดอาจยาวขึ้น แต่ผู้อ่านเข้าใจได้ทันที

object Main {
  case class Celsius(value: Double)
  def fromDouble(d: Double): Celsius = Celsius(d)
  def main(args: Array[String]): Unit = {
    val c = fromDouble(20.5)
    println(c)
  }
}

Scala 3: คลาสชนิด Conversion

Scala 3 ทำให้การแปลงชัดเจนขึ้นผ่านอินสแตนซ์ given Conversion[A, B] วิธีนี้สื่อเจตนาได้ชัดกว่า และยังจำเป็นต้องนำเข้าความสามารถของภาษา

import scala.language.implicitConversions

object Main:
  given Conversion[Int, String] = (x: Int) => s"val-$x"
  def main(args: Array[String]): Unit =
    val s: String = 7
    println(s)

การแปลงมีผลได้เพียงครั้งเดียว

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

object Main {
  import scala.language.implicitConversions
  implicit def intToStr(x: Int): String = x.toString
  def needString(s: String): Int = s.length
  def main(args: Array[String]): Unit = {
    println(needString(12345))
  }
}

ค้นพบการแปลงได้ที่ใด

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

object Conversions:
  import scala.language.implicitConversions
  implicit def strToLen(s: String): Int = s.length

object Main:
  import Conversions._
  def main(args: Array[String]): Unit =
    val n: Int = "hello"
    println(n)

กรณีที่การแปลงเหมาะสม

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

object Main {
  import scala.language.implicitConversions
  case class Meters(v: Double)
  implicit def metersToDouble(m: Meters): Double = m.v
  def main(args: Array[String]): Unit = {
    val d: Double = Meters(3.5)
    println(d * 2)
  }
}

หลักโดยสังเขป

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

object Main {
  // Explicit and obvious - usually better
  case class Price(cents: Int)
  def toDollars(p: Price): Double = p.cents / 100.0
  def main(args: Array[String]): Unit = {
    println(toDollars(Price(1599)))
  }
}

ตรวจสอบอย่างรวดเร็ว

ความเสี่ยงหลักของการแปลงโดยนัยคืออะไร

สรุปทบทวน

คุณได้เรียนรู้การแปลงโดยนัยและข้อควรระวังแล้ว:

  • ระบบจะแปลงชนิดหนึ่งเป็นอีกชนิดหนึ่งโดยอัตโนมัติเมื่อชนิดไม่ตรงกัน
  • ต้องใช้ import scala.language.implicitConversions
  • Scala 3 ใช้ given Conversion[A, B]
  • ระบบจะใช้การแปลงได้ครั้งละหนึ่งรายการเท่านั้น
  • ควรใช้เท่าที่จำเป็น และเลือกใช้เมธอดส่วนขยายหรือการเรียกอย่างชัดเจนแทน

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

บทเรียน “การแปลงโดยนัย” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “การแปลงโดยนัย”

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

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่

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

บทเรียน “การแปลงโดยนัย” ใช้เวลานานแค่ไหน

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

ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม

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

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

  1. พารามิเตอร์โดยนัย
  2. given/using ใน Scala 3
  3. การแปลงโดยนัย
  4. เมธอดส่วนขยาย
← กลับไปที่ Scala for Backend Engineering & Functional Programming