0Pricing
Scala for Backend Engineering & Functional Programming · Lezione

Corrispondenza di tipi e valori

Pattern di tipo

Corrispondenza di tipi e valori è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Scala for Backend Engineering & Functional Programming, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.

Pattern di tipo

Oltre a confrontare valori letterali, match può diramare in base al tipo di un valore. Questo viene chiamato pattern di tipo.

Si scrive case x: Type => e il ramo viene eseguito quando il valore è di quel tipo, associandolo a x.

Confrontare in base al tipo

Quando un valore ha un tipo generico come Any, è possibile individuarne il tipo concreto con un pattern di tipo.

Ogni case x: T verifica il tipo a runtime.

object Main {
  def describe(x: Any): String = x match {
    case i: Int    => "an Int"
    case s: String => "a String"
    case _         => "something else"
  }
  def main(args: Array[String]): Unit = {
    println(describe(5))
    println(describe("hi"))
    println(describe(3.14))
  }
}

Usare il valore associato

Il nome associato ha il tipo del valore corrispondente, quindi è possibile chiamarne i metodi in sicurezza all'interno di quel ramo.

Non è necessario alcun cast: il compilatore conosce il tipo all'interno del caso.

object Main {
  def shout(x: Any): String = x match {
    case s: String => s.toUpperCase
    case i: Int    => (i * 2).toString
    case _         => "?"
  }
  def main(args: Array[String]): Unit = {
    println(shout("hello"))
    println(shout(21))
  }
}

Tipo e valore insieme

È possibile combinare pattern di valore e pattern di tipo nello stesso match. I pattern di valore sono solitamente più specifici, quindi li inserisca per primi.

object Main {
  def check(x: Any): String = x match {
    case 0       => "zero int"
    case i: Int  => s"nonzero int $i"
    case _       => "not an int"
  }
  def main(args: Array[String]): Unit = {
    println(check(0))
    println(check(7))
    println(check("x"))
  }
}

Confrontare Double e Boolean

I pattern di tipo funzionano con qualsiasi tipo, inclusi Double, Boolean e Char.

object Main {
  def kind(x: Any): String = x match {
    case d: Double  => s"double $d"
    case b: Boolean => s"bool $b"
    case _          => "other"
  }
  def main(args: Array[String]): Unit = {
    println(kind(2.5))
    println(kind(true))
  }
}

Confrontare collezioni in base al tipo

È possibile confrontare anche tipi contenitore come List. Qui distinguiamo una lista dagli altri valori.

object Main {
  def info(x: Any): String = x match {
    case l: List[_] => s"a list of size ${l.size}"
    case _          => "not a list"
  }
  def main(args: Array[String]): Unit = {
    println(info(List(1, 2, 3)))
    println(info("nope"))
  }
}

Un uso comune: gestire Any

I pattern di tipo sono particolarmente utili quando una funzione riceve Any e deve reagire in modo diverso a seconda del tipo, ad esempio per la registrazione o la serializzazione.

object Main {
  def render(x: Any): String = x match {
    case i: Int    => s"int=$i"
    case d: Double => s"dbl=$d"
    case s: String => s"str=$s"
    case _         => "unknown"
  }
  def main(args: Array[String]): Unit = {
    List(1, 2.0, "three").foreach(v => println(render(v)))
  }
}

L'ordine è ancora importante

Come per tutti i match, i pattern di tipo vengono verificati dall'alto verso il basso. Un tipo più generale inserito per primo può nascondere un tipo più specifico sottostante.

Ordini sempre i casi dal più specifico al più generale.

object Main {
  def label(x: Any): String = x match {
    case s: String => "string first"
    case _: Any    => "anything"
  }
  def main(args: Array[String]): Unit = {
    println(label("hi"))
    println(label(99))
  }
}

La limitazione del type erasure

Durante l'esecuzione, i parametri di tipo generici vengono cancellati. Di conseguenza, List[Int] e List[String] appaiono uguali. Il confronto con List[Int] verifica soltanto che si tratti di una List.

Usi List[_] per essere esplicito ed evitare avvisi.

Perché usare i pattern di tipo?

I pattern di tipo consentono di:

  • restringere in sicurezza un tipo generico senza ricorrere ai cast
  • gestire in modo ordinato valori eterogenei
  • combinarsi con pattern di valore e guardie

Sono un punto di partenza per il pattern matching su case class e ADT.

Mettere tutto insieme

Combini pattern di valore e pattern di tipo per classificare input eterogenei.

object Main {
  def classify(x: Any): String = x match {
    case 0          => "zero"
    case i: Int     => "int"
    case s: String  => "text of length " + s.length
    case _          => "other"
  }
  def main(args: Array[String]): Unit = {
    println(classify(0))
    println(classify(5))
    println(classify("hey"))
  }
}

Verifica rapida

Verifichi la Sua conoscenza dei pattern di tipo.

Riepilogo

Ha imparato a confrontare i tipi:

  • case x: Type confronta il tipo a runtime e associa il valore a x
  • il valore associato ha il tipo corrispondente, quindi non è necessario alcun cast
  • combini pattern di valore e di tipo, partendo da quelli più specifici
  • i parametri generici vengono cancellati, quindi usi List[_]

Domande Frequenti

La lezione «Corrispondenza di tipi e valori» è gratuita?

Sì — il testo completo di «Corrispondenza di tipi e valori» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Scala for Backend Engineering & Functional Programming, passa a CoddyKit PRO. Il corso Scala for Backend Engineering & Functional Programming include 4 lezioni in totale.

Cosa imparerò in «Corrispondenza di tipi e valori»?

Pattern di tipo Eserciti Scala for Backend Engineering & Functional Programming con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Scala for Backend Engineering & Functional Programming?

Non è richiesta alcuna esperienza precedente. Scala for Backend Engineering & Functional Programming su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Corrispondenza di tipi e valori»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Scala for Backend Engineering & Functional Programming?

Sì. Ogni lezione Scala for Backend Engineering & Functional Programming include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Espressioni match
  2. Corrispondenza di tipi e valori
  3. Guardie e binding
  4. Decomposizione
← Torna a Scala for Backend Engineering & Functional Programming