0Pricing
Scala for Backend Engineering & Functional Programming · Aula

Definindo instâncias

Instâncias implícitas.

Definindo instâncias é uma aula grátis de Scala for Backend Engineering & Functional Programming no CoddyKit. Esta é a aula 2 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.

Definindo instâncias

Uma instância informa ao compilador como uma classe de tipos se comporta para um tipo específico. Em Scala, as instâncias geralmente são marcadas como implicit (Scala 2) ou declaradas com given (Scala 3), para que sejam encontradas automaticamente.

Uma instância implicit val

Para uma classe de tipos simples, um implicit val é suficiente. O compilador o encontra quando uma função precisa de um Show[Int].

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: invocando uma instância

implicitly[Show[Int]] solicita ao compilador a instância disponível no escopo. Isso é útil para testar se uma instância existe ou para acessá-la diretamente.

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

Instâncias para tipos personalizados

Defina uma instância para sua própria classe de caso. A classe de dados permanece limpa; a formatação fica na instância.

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 para instâncias genéricas

Quando uma instância depende de outra instância, use implicit def. Aqui, um Show[List[A]] é construído a partir de um Show[A].

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

Instâncias no objeto acompanhante

Colocar instâncias no objeto acompanhante da classe de tipos faz com que elas sejam encontradas automaticamente, sem qualquer importação. Esse é o local recomendado para as instâncias padrão.

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

Escopo e prioridade de implicits

O compilador procura uma instância em vários lugares: primeiro no escopo local ou importado e, depois, nos objetos acompanhantes dos tipos envolvidos. Se duas instâncias forem igualmente específicas, você receberá um erro de implicit ambíguo.

Forma abreviada de limite de contexto

A sintaxe def f[A: Show](a: A) é um limite de contexto: significa que deve haver um Show[A] implícito no escopo. Dentro da função, recupere-o com implicitly.

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

Um auxiliar para invocação

As bibliotecas adicionam um método apply ao objeto acompanhante como um invocador conveniente: Show[Int] retorna a instância. Isso é mais limpo do que usar 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))
  }
}

Evitando instâncias órfãs

Uma instância órfã é definida fora da classe de tipos e também fora do tipo. Elas são válidas, mas podem causar comportamentos inconsistentes entre importações. Prefira instâncias em objetos acompanhantes para mantê-las coerentes.

Reunindo tudo

Um programa completo: instâncias em objetos acompanhantes, uma instância de lista derivada e um invocador.

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

Verificação rápida

Teste seus conhecimentos sobre a definição de instâncias.

Recapitulação

Você aprendeu a definir instâncias:

  • implicit val para instâncias simples e implicit def para as derivadas.
  • Invoque com implicitly ou com um apply do objeto acompanhante.
  • Use limites de contexto [A: Show] como forma abreviada.
  • Coloque as instâncias em objetos acompanhantes para evitar órfãs.

Perguntas Frequentes

A aula “Definindo instâncias” é grátis?

Sim — o texto completo de “Definindo instâncias” é 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 “Definindo instâncias”?

Instâncias implícitas. 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 2 de 4.

Quanto tempo leva a aula “Definindo instâncias”?

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

  1. O padrão de classe de tipos
  2. Definindo instâncias
  3. Classes de tipos comuns
  4. Derivação de classes de tipos
← Voltar para Scala for Backend Engineering & Functional Programming