0Pricing
Scala for Backend Engineering & Functional Programming · Lektion

Instanzen definieren

Implizite Instanzen

Instanzen definieren ist eine kostenlose Scala for Backend Engineering & Functional Programming-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Scala for Backend Engineering & Functional Programming-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Scala for Backend Engineering & Functional Programming-Kurs umfasst insgesamt 4 Lektionen.

Instanzen definieren

Eine Instanz teilt dem Compiler mit, wie sich eine Typklasse für einen bestimmten Typ verhält. In Scala werden Instanzen normalerweise mit implicit (Scala 2) markiert oder mit given (Scala 3) deklariert, damit sie automatisch gefunden werden.

Eine implizite val-Instanz

Für eine einfache Typklasse genügt ein implicit val. Der Compiler findet ihn, wenn eine Funktion ein Show[Int] benötigt.

trait Show[A] { def show(a: A): String }

object Main {
  implicit val intShow: Show[Int] = (a: Int) => s"Int=$a"

  def display[A](a: A)(implicit s: Show[A]): String = s.show(a)

  def main(args: Array[String]): Unit = {
    println(display(123))
  }
}

implicitly: Eine Instanz abrufen

implicitly[Show[Int]] weist den Compiler an, die im Gültigkeitsbereich vorhandene Instanz abzurufen. Das ist nützlich, um zu testen, ob eine Instanz existiert, oder um direkt auf sie zuzugreifen.

trait Show[A] { def show(a: A): String }

object Main {
  implicit val intShow: Show[Int] = (a: Int) => s"<$a>"

  def main(args: Array[String]): Unit = {
    val s = implicitly[Show[Int]]
    println(s.show(8))
  }
}

Instanzen für eigene Typen

Definieren Sie eine Instanz für Ihre eigene Case-Klasse. Die Datenklasse bleibt übersichtlich; die Formatierung befindet sich in der Instanz.

trait Show[A] { def show(a: A): String }

case class Point(x: Int, y: Int)

object Main {
  implicit val pointShow: Show[Point] = (p: Point) => s"(${p.x}, ${p.y})"

  def display[A](a: A)(implicit s: Show[A]): String = s.show(a)

  def main(args: Array[String]): Unit = {
    println(display(Point(3, 4)))
  }
}

implicit def für generische Instanzen

Wenn eine Instanz von einer anderen Instanz abhängt, verwenden Sie implicit def. Hier wird ein Show[List[A]] aus einem Show[A] erstellt.

trait Show[A] { def show(a: A): String }

object Main {
  implicit val intShow: Show[Int] = (a: Int) => a.toString

  implicit def listShow[A](implicit s: Show[A]): Show[List[A]] =
    (xs: List[A]) => xs.map(s.show).mkString("[", ", ", "]")

  def display[A](a: A)(implicit s: Show[A]): String = s.show(a)

  def main(args: Array[String]): Unit = {
    println(display(List(1, 2, 3)))
  }
}

Instanzen im Companion-Objekt

Wenn Sie Instanzen im Companion-Objekt der Typklasse platzieren, werden sie automatisch und ohne Import gefunden. Das ist der empfohlene Ort für Standardinstanzen.

trait Show[A] { def show(a: A): String }

object Show {
  implicit val intShow: Show[Int] = (a: Int) => s"i:$a"
  implicit val strShow: Show[String] = (a: String) => s"s:$a"
}

object Main {
  def display[A](a: A)(implicit s: Show[A]): String = s.show(a)

  def main(args: Array[String]): Unit = {
    println(display(5))
    println(display("hi"))
  }
}

Gültigkeitsbereich und Priorität impliziter Werte

Der Compiler sucht an mehreren Stellen nach einer Instanz: zuerst im lokalen beziehungsweise importierten Gültigkeitsbereich, danach in den Companion-Objekten der beteiligten Typen. Sind zwei Instanzen gleich spezifisch, erhalten Sie einen Fehler wegen eines mehrdeutigen impliziten Werts.

Kurzschreibweise für Context Bounds

Die Syntax def f[A: Show](a: A) ist ein Context Bound: Sie bedeutet, dass ein implizites Show[A] im Gültigkeitsbereich vorhanden sein muss. Rufen Sie es innerhalb der Funktion mit implicitly ab.

trait Show[A] { def show(a: A): String }

object Main {
  implicit val intShow: Show[Int] = (a: Int) => s"n=$a"

  def display[A: Show](a: A): String = implicitly[Show[A]].show(a)

  def main(args: Array[String]): Unit = {
    println(display(77))
  }
}

Eine Hilfsfunktion zum Abrufen

Bibliotheken ergänzen das Companion-Objekt um eine apply-Methode als praktischen Summoner: Show[Int] gibt die Instanz zurück. Das ist übersichtlicher als implicitly.

trait Show[A] { def show(a: A): String }

object Show {
  def apply[A](implicit s: Show[A]): Show[A] = s
  implicit val intShow: Show[Int] = (a: Int) => s"=$a"
}

object Main {
  def main(args: Array[String]): Unit = {
    println(Show[Int].show(10))
  }
}

Verwaiste Instanzen vermeiden

Eine verwaiste Instanz ist eine Instanz, die weder zusammen mit der Typklasse noch zusammen mit dem Typ definiert ist. Sie ist zwar zulässig, kann aber über verschiedene Imports hinweg zu inkonsistentem Verhalten führen. Bevorzugen Sie Instanzen in Companion-Objekten, damit sie konsistent bleiben.

Alles zusammenführen

Ein vollständiges Programm mit Instanzen im Companion-Objekt, einer abgeleiteten Listeninstanz und einem Summoner.

trait Show[A] { def show(a: A): String }

object Show {
  def apply[A](implicit s: Show[A]): Show[A] = s
  implicit val intShow: Show[Int] = _.toString
  implicit def listShow[A](implicit s: Show[A]): Show[List[A]] =
    (xs: List[A]) => xs.map(s.show).mkString(", ")
}

object Main {
  def main(args: Array[String]): Unit = {
    println(Show[List[Int]].show(List(4, 5, 6)))
  }
}

Kurze Überprüfung

Testen Sie Ihr Wissen über das Definieren von Instanzen.

Zusammenfassung

Sie haben gelernt, Instanzen zu definieren:

  • implicit val für einfache Instanzen, implicit def für abgeleitete Instanzen.
  • Rufen Sie Instanzen mit implicitly oder einem apply im Companion-Objekt ab.
  • Verwenden Sie Context Bounds [A: Show] als Kurzschreibweise.
  • Platzieren Sie Instanzen in Companion-Objekten, um verwaiste Instanzen zu vermeiden.

Häufig gestellte Fragen

Ist die Lektion „Instanzen definieren“ kostenlos?

Ja — der vollständige Text von „Instanzen definieren“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Scala for Backend Engineering & Functional Programming-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Scala for Backend Engineering & Functional Programming-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Instanzen definieren“?

Implizite Instanzen Du übst Scala for Backend Engineering & Functional Programming mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Scala for Backend Engineering & Functional Programming zu starten?

Keine Vorkenntnisse erforderlich. Scala for Backend Engineering & Functional Programming auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Instanzen definieren“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Scala for Backend Engineering & Functional Programming-Lektion Code schreiben und ausführen?

Ja. Jede Scala for Backend Engineering & Functional Programming-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Das Type-Class-Muster
  2. Instanzen definieren
  3. Gängige Typeclasses
  4. Ableitung von Typeclasses
← Zurück zu Scala for Backend Engineering & Functional Programming