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

พารามิเตอร์โดยนัย

การส่งผ่านบริบท

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

การส่งบริบทโดยอัตโนมัติ

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

object Main {
  def greet(name: String)(implicit greeting: String): String =
    s"$greeting, $name!"
  implicit val defaultGreeting: String = "Hello"
  def main(args: Array[String]): Unit = {
    println(greet("Ann"))
  }
}

รายการพารามิเตอร์โดยนัย

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

object Main {
  def multiply(x: Int)(implicit factor: Int): Int = x * factor
  implicit val f: Int = 10
  def main(args: Array[String]): Unit = {
    println(multiply(5))
  }
}

การระบุค่าโดยนัยอย่างชัดเจน

คุณสามารถส่งพารามิเตอร์โดยนัยอย่างชัดเจนได้เสมอ ซึ่งจะเขียนทับค่าที่อยู่ในขอบเขต เหมาะสำหรับกรณีเฉพาะครั้ง

object Main {
  def multiply(x: Int)(implicit factor: Int): Int = x * factor
  implicit val f: Int = 10
  def main(args: Array[String]): Unit = {
    println(multiply(5))
    println(multiply(5)(2))
  }
}

การแก้ค่าพารามิเตอร์โดยนัยตามชนิด

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

object Main {
  case class Config(env: String)
  def run()(implicit cfg: Config): String = s"running in ${cfg.env}"
  implicit val cfg: Config = Config("prod")
  def main(args: Array[String]): Unit = {
    println(run())
  }
}

ใช้ implicitly เพื่อดึงค่า

ตัวช่วย implicitly[T] จะดึงค่าโดยนัยชนิด T จากขอบเขตโดยตรง โดยไม่ต้องระบุชื่อพารามิเตอร์

object Main {
  implicit val name: String = "Scala"
  def main(args: Array[String]): Unit = {
    val n = implicitly[String]
    println(n)
  }
}

รูปแบบย่อของขอบเขตบริบท

ขอบเขตบริบท [T: Ordering] เป็นรูปแบบย่อของพารามิเตอร์โดยนัยชนิด Ordering[T] มักใช้ร่วมกับคลาสชนิด

object Main {
  def max[T: Ordering](a: T, b: T): T = {
    val ord = implicitly[Ordering[T]]
    if (ord.gt(a, b)) a else b
  }
  def main(args: Array[String]): Unit = {
    println(max(3, 7))
    println(max("apple", "pear"))
  }
}

ส่งต่อบริบทผ่านการเรียก

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

object Main {
  case class User(name: String)
  def log(msg: String)(implicit u: User): Unit =
    println(s"[${u.name}] $msg")
  def doWork()(implicit u: User): Unit = {
    log("started")
    log("finished")
  }
  implicit val current: User = User("admin")
  def main(args: Array[String]): Unit = {
    doWork()
  }
}

คอมไพเลอร์ค้นหาค่าโดยนัยที่ใด

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

object Main {
  case class Currency(symbol: String)
  object Currency {
    implicit val default: Currency = Currency("$")
  }
  def price(amount: Int)(implicit c: Currency): String = s"${c.symbol}$amount"
  def main(args: Array[String]): Unit = {
    println(price(50))
  }
}

ข้อผิดพลาดจากความคลุมเครือ

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

object Main {
  def label(x: Int)(implicit unit: String): String = s"$x$unit"
  implicit val unit: String = "px"
  def main(args: Array[String]): Unit = {
    // Only one implicit String in scope -> no ambiguity
    println(label(12))
  }
}

พฤติกรรมคล้ายค่าเริ่มต้น

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

object Main {
  def format(n: Double)(implicit decimals: Int): String =
    f"$n%.${decimals}f"
  implicit val d: Int = 2
  def main(args: Array[String]): Unit = {
    println(format(3.14159))
    println(format(3.14159)(4))
  }
}

ใช้ค่าโดยนัยอย่างพอเหมาะ

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

object Main {
  case class Locale(code: String)
  def hello()(implicit loc: Locale): String =
    if (loc.code == "tr") "Merhaba" else "Hello"
  implicit val loc: Locale = Locale("tr")
  def main(args: Array[String]): Unit = {
    println(hello())
  }
}

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

คอมไพเลอร์ตัดสินใจอย่างไรว่าจะจัดหาค่าใดให้พารามิเตอร์โดยนัย

สรุปทบทวน

คุณได้เรียนรู้พารามิเตอร์โดยนัย (รูปแบบของ Scala 2) ดังนี้:

  • ทำเครื่องหมายรายการพารามิเตอร์ด้วย implicit เพื่อให้ระบบเติมค่าโดยอัตโนมัติ
  • การแก้ค่าทำตามชนิด และต้องมีค่าไม่ซ้ำกันในขอบเขต
  • implicitly[T] ใช้ดึงค่า ส่วนขอบเขตบริบท [T: TC] เป็นรูปแบบย่อ
  • การค้นหาครอบคลุมขอบเขตเฉพาะที่ การนำเข้า และออบเจ็กต์คู่หู
  • ใช้สำหรับบริบทที่ใช้ข้ามส่วน ไม่ใช่สำหรับทุกสิ่ง

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

บทเรียน “พารามิเตอร์โดยนัย” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “พารามิเตอร์โดยนัย” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ 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 ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 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