0Pricing
Scala for Backend Engineering & Functional Programming · Lección

Tipos unión e intersección

Nuevas características de tipos

Tipos unión e intersección es una lección gratuita de Scala for Backend Engineering & Functional Programming en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Scala for Backend Engineering & Functional Programming, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Scala for Backend Engineering & Functional Programming incluye 4 lecciones en total.

Nuevas características de tipos

Scala 3 añade tipos unión (A | B) y tipos intersección (A & B) al sistema de tipos. Permiten describir los valores con mayor precisión sin jerarquías de herencia.

object Main:
  def main(args: Array[String]): Unit =
    println("Union: A | B, Intersection: A & B")

Conceptos básicos de los tipos unión

Un tipo unión A | B representa un valor que es A o B. Es un OR de teoría de conjuntos aplicado a los tipos.

object Main:
  def show(x: Int | String): String = x match
    case i: Int    => s"int $i"
    case s: String => s"str $s"

  def main(args: Array[String]): Unit =
    println(show(42))
    println(show("hi"))

Las uniones no necesitan un supertipo común

A diferencia de Either en Scala 2, los tipos unión no requieren un envoltorio. Se puede crear la unión de cualesquiera dos tipos sin que compartan una clase padre.

object Main:
  def parse(input: Int | Boolean): String =
    input match
      case n: Int     => s"number $n"
      case b: Boolean => s"flag $b"

  def main(args: Array[String]): Unit =
    println(parse(7))
    println(parse(true))

Uniones para modelar errores

Los tipos unión resultan prácticos para representar resultados de error ligeros sin un tipo envoltorio. Combinados con enums o singletons, producen código claro.

case object NotFound

object Main:
  def lookup(id: Int): String | NotFound.type =
    if id == 1 then "Alice" else NotFound

  def main(args: Array[String]): Unit =
    println(lookup(1))
    println(lookup(2))

Conceptos básicos de los tipos intersección

Un tipo intersección A & B representa un valor que es a la vez A y B. Es un AND de teoría de conjuntos, que suele utilizarse para combinar traits.

trait Named:
  def name: String
trait Aged:
  def age: Int

object Main:
  def describe(p: Named & Aged): String =
    s"${p.name} is ${p.age}"

  def main(args: Array[String]): Unit =
    val person = new Named with Aged:
      def name = "Bob"
      def age = 40
    println(describe(person))

La intersección es conmutativa

El orden no importa en los tipos intersección: A & B es el mismo tipo que B & A. Esto difiere de los tipos compuestos A with B de Scala 2, que dependían del orden en algunas resoluciones de miembros.

trait Readable:
  def read: String
trait Writable:
  def write(s: String): Unit

object Main:
  def use(r: Readable & Writable): Unit =
    r.write("x")
    println(r.read)

  def main(args: Array[String]): Unit =
    val rw = new Readable with Writable:
      def read = "data"
      def write(s: String) = println(s"wrote $s")
    use(rw)

Combinación de varios traits

Puede intersecar más de dos tipos. El resultado requiere todas las capacidades indicadas.

trait A: def a: Int
trait B: def b: Int
trait C: def c: Int

object Main:
  def sum(x: A & B & C): Int = x.a + x.b + x.c

  def main(args: Array[String]): Unit =
    val v = new A with B with C:
      def a = 1
      def b = 2
      def c = 3
    println(sum(v))

Aliases de tipo para uniones

Puede asignar un nombre a los tipos unión largos mediante un alias de type para mantener legibles las signaturas.

type Json = Int | String | Boolean

object Main:
  def render(j: Json): String = j match
    case i: Int     => i.toString
    case s: String  => s"\"$s\""
    case b: Boolean => b.toString

  def main(args: Array[String]): Unit =
    println(render("hi"))
    println(render(true))

Coincidencia exhaustiva en uniones

El compilador conoce los miembros de una unión, por lo que puede comprobar que la coincidencia sea completa. Gestionar todas las alternativas hace que el match sea total.

type Shape = "circle" | "square"

object Main:
  def sides(s: Shape): Int = s match
    case "circle" => 0
    case "square" => 4

  def main(args: Array[String]): Unit =
    println(sides("square"))

Ensanchamiento de las uniones

Al asignar un valor unión a una variable cuyo tipo se infiere, Scala conserva el tipo unión. Tenga en cuenta que algunas operaciones lo ensanchan hasta el mínimo supertipo común, así que use una anotación cuando quiera conservar la unión.

object Main:
  def pick(flag: Boolean): Int | String =
    if flag then 1 else "one"

  def main(args: Array[String]): Unit =
    val x: Int | String = pick(false)
    println(x)

Cuándo usar cada uno

Elija la herramienta adecuada.

  • Unión: un valor es de uno de varios tipos (OR).
  • Intersección: un valor satisface varios rasgos a la vez (AND).
  • Las uniones evitan los tipos envoltorio; las intersecciones evitan las jerarquías de herencia profundas.
trait Logger: def log(s: String): Unit
trait Clock:  def now: Long

object Main:
  def run(env: Logger & Clock): Unit =
    env.log(s"time=${env.now}")

  def main(args: Array[String]): Unit =
    val env = new Logger with Clock:
      def log(s: String) = println(s)
      def now = 100L
    run(env)

Comprobación rápida

Compruebe su comprensión de los tipos unión e intersección.

Resumen

Ha aprendido los tipos unión e intersección de Scala 3.

  • A | B: el valor es A o B; no necesita un envoltorio ni un padre común.
  • A & B: el valor es A y B a la vez; es conmutativo.
  • Use pattern matching para acotar las uniones y combine rasgos mediante intersecciones.
  • Use alias de tipo con type para dar nombre a las uniones largas.
object Main:
  def length(x: String | List[Int]): Int = x match
    case s: String    => s.length
    case l: List[Int] => l.length

  def main(args: Array[String]): Unit =
    println(length("hello"))
    println(length(List(1, 2, 3)))

Preguntas frecuentes

¿La lección «Tipos unión e intersección» es gratis?

Sí — el texto completo de «Tipos unión e intersección» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Scala for Backend Engineering & Functional Programming, actualiza a CoddyKit PRO. El curso de Scala for Backend Engineering & Functional Programming incluye 4 lecciones en total.

¿Qué aprenderé en «Tipos unión e intersección»?

Nuevas características de tipos Practicas Scala for Backend Engineering & Functional Programming con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Scala for Backend Engineering & Functional Programming?

No se requiere experiencia previa. Scala for Backend Engineering & Functional Programming en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Tipos unión e intersección»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Scala for Backend Engineering & Functional Programming?

Sí. Cada lección de Scala for Backend Engineering & Functional Programming incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Indentación significativa
  2. Enums en Scala 3
  3. Tipos opacos
  4. Tipos unión e intersección
← Volver a Scala for Backend Engineering & Functional Programming