Scala til backendudvikling og funktionel programmering · Lektion

Implicitte konverteringer

Brug med omtanke

Lektion 3 af 413 trin

Implicitte konverteringer er en gratis Scala til backendudvikling og funktionel programmering-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Scala til backendudvikling og funktionel programmering, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Scala til backendudvikling og funktionel programmering-kurset indeholder 4 lektioner i alt.

Hvad er en implicit konvertering?

En implicit konvertering omdanner automatisk en værdi fra én type til en anden, når compileren har brug for det. Det kan gøre API'er mere praktiske, men skal bruges med omtanke, fordi det skjuler, hvad der sker.

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)
  }
}

Sådan bruger compileren dem

Når en værdis type ikke matcher det forventede, søger compileren efter en implicit konvertering, der løser uoverensstemmelsen, og indsætter den ubemærket.

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))
  }
}

Aktivering af funktionen

Det kræver import af scala.language.implicitConversions at definere implicitte konverteringer, ellers advarer compileren dig. Det er en bevidst hindring, der skal modvirke overforbrug.

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))
  }
}

Indpakning for ekstra metoder (gammel stil)

Før udvidelsesmetoder var implicitte konverteringer til en wrapperklasse måden at »tilføje« metoder til eksisterende typer på, det såkaldte pimp-my-library-mønster.

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)
  }
}

Faren: skjulte overraskelser

Da konverteringer er usynlige ved kaldet, kan de føre til forvirrende funktionalitet og fejl, som er svære at spore. En slåfejl kan måske kompilere ved ved et uheld at udløse en konvertering.

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)
  }
}

Foretræk eksplicit konvertering

Ofte er det sikreste valg en almindelig navngiven metode i stedet for en implicit konvertering. Koden bliver længere, men tydelig for læserne.

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: typeklassen Conversion

Scala 3 gør konverteringer eksplicitte via en given Conversion[A, B]-instans. Det gør hensigten tydeligere og kræver stadig sprogimporten.

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)

Konverteringer anvendes kun én gang

Compileren anvender højst én implicit konvertering ad gangen. Den kæder ikke to konverteringer sammen for at bygge bro over en forskel, hvilket begrænser overraskelser.

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))
  }
}

Hvor konverteringer findes

Ligesom andre implicitter opløses konverteringer fra lokale synlighedsområder, imports og ledsageobjekter. Hvis du placerer dem i en tydeligt navngiven import, bliver deres tilstedeværelse synlig.

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)

Hvornår konverteringer er rimelige

Berettigede anvendelser omfatter interoperabilitet med Java-typer, hjælp til numerisk udvidelse og grænser mellem biblioteker. Uden for disse tilfælde bør du foretrække udvidelsesmetoder eller eksplicitte funktioner.

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)
  }
}

Tommelfingerregel

Hvis en læser ikke kan se i koden, at der sker en konvertering, er det et advarselstegn. Brug implicitte konverteringer som sidste udvej, efter udvidelsesmetoder og eksplicitte kald.

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)))
  }
}

Hurtigt tjek

Hvad er den største risiko ved implicitte konverteringer?

Opsummering

Du har lært om implicitte konverteringer og deres forbehold:

  • De konverterer automatisk én type til en anden, når typerne ikke stemmer overens
  • Kræver import scala.language.implicitConversions
  • Scala 3 bruger given Conversion[A, B]
  • Der anvendes kun én konvertering ad gangen
  • Brug dem sparsomt; foretræk udvidelsesmetoder eller eksplicitte kald
Gratis at komme i gang

Lær Scala med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
39
Lektioner
143

Ofte stillede spørgsmål

Er lektionen “Implicitte konverteringer” gratis?

Ja — hele teksten til “Implicitte konverteringer” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Scala til backendudvikling og funktionel programmering-kurset, skal du opgradere til CoddyKit PRO. Scala til backendudvikling og funktionel programmering-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Implicitte konverteringer”?

Brug med omtanke Du øver dig i Scala til backendudvikling og funktionel programmering med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Scala til backendudvikling og funktionel programmering?

Der kræves ingen tidligere erfaring. Scala til backendudvikling og funktionel programmering på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Implicitte konverteringer”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Scala til backendudvikling og funktionel programmering-lektion?

Ja. Alle Scala til backendudvikling og funktionel programmering-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Implicitte parametre
  2. Scala 3 given/using
  3. Implicitte konverteringer
  4. Extension methods
← Tilbage til Scala til backendudvikling og funktionel programmering