Tipos união e interseção
Novos recursos de tipos
Tipos união e interseção é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Scala for Backend Engineering & Functional Programming, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
Novos recursos de tipos
Scala 3 adiciona tipos união (A | B) e tipos interseção (A & B) ao sistema de tipos. Eles permitem descrever valores com mais precisão, sem hierarquias de herança.
object Main:
def main(args: Array[String]): Unit =
println("Union: A | B, Intersection: A & B")Noções básicas dos tipos união
Um tipo união A | B representa um valor que é A ou B. Ele corresponde a um OU da teoria dos conjuntos aplicado aos 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"))Uniões não precisam de um supertipo comum
Ao contrário de Either no Scala 2, os tipos união não exigem encapsulamento. Quaisquer dois tipos podem formar uma união sem compartilhar uma classe pai.
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))Uniões para modelar erros
Os tipos união são úteis para resultados de erro leves, sem um tipo wrapper. Combinados com enums ou singletons, eles ficam fáceis de ler.
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))Noções básicas dos tipos interseção
Um tipo de interseção A & B representa um valor que é tanto A quanto B. Trata-se de um AND da teoria dos conjuntos, frequentemente usado para combinar características.
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))A interseção é comutativa
A ordem não importa nos tipos de interseção: A & B é o mesmo tipo que B & A. Isso difere dos tipos compostos da Scala 2, A with B, nos quais a ordem afetava a resolução de alguns membros.
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)Combinando várias características
É possível fazer a interseção de mais de dois tipos. O resultado exige todas as capacidades listadas.
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 uniões
Tipos de união longos podem receber um nome com um alias type, mantendo as assinaturas legíveis.
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))Correspondência exaustiva em uniões
O compilador conhece os membros de uma união, portanto pode verificar se a correspondência está completa. Tratar todas as alternativas torna a correspondência 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"))Alargamento de uniões
Ao atribuir um valor de união a uma variável cujo tipo é inferido, a Scala mantém o tipo de união. Tenha em mente que algumas operações alargam o tipo para o menor supertipo comum; por isso, use uma anotação quando quiser preservar a união.
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)Quando usar cada recurso
Escolha a ferramenta certa.
- União: um valor é um entre vários tipos (OR).
- Interseção: um valor satisfaz várias características ao mesmo tempo (AND).
- As uniões evitam tipos contêiner; as interseções evitam hierarquias de herança 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)Verificação rápida
Teste sua compreensão dos tipos de união e de interseção.
Recapitulação
Você aprendeu os tipos de união e de interseção da Scala 3.
A | B: o valor é A ou B, sem necessidade de um contêiner ou de um pai comum.A & B: o valor é A e B ao mesmo tempo; a operação é comutativa.- Use correspondência de padrões para restringir uniões; combine características com interseções.
- Use aliases
typepara nomear uniões longas.
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)))Perguntas Frequentes
A aula “Tipos união e interseção” é grátis?
Sim — o texto completo de “Tipos união e interseção” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Scala for Backend Engineering & Functional Programming, atualize para CoddyKit PRO. O curso de Scala for Backend Engineering & Functional Programming inclui 4 aulas no total.
O que vou aprender em “Tipos união e interseção”?
Novos recursos de tipos Você pratica Scala for Backend Engineering & Functional Programming com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Scala for Backend Engineering & Functional Programming?
Nenhuma experiência prévia é necessária. Scala for Backend Engineering & Functional Programming no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Tipos união e interseção”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Scala for Backend Engineering & Functional Programming?
Sim. Cada aula de Scala for Backend Engineering & Functional Programming inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Indentação significativa
- Enums no Scala 3
- Tipos opacos
- Tipos união e interseção