Pular para o conteúdo

Boas práticas e padrões · Princípios SOLID · 5 min de leitura

L — Princípio da substituição de Liskov (LSP)

Um subtipo precisa funcionar em qualquer lugar onde o tipo base funciona, sem surpresas para quem chama.

Cliente → Ave: voar()voar()Ave → PardalAve → Pinguim: quebraquebraCliente — conta com o contratoClienteconta com o contratoAve — contrato: voar()Avecontrato: voar()Pardal — cumprePardalcumprePinguim — lança exceção!Pinguimlança exceção!

Arraste para o lado para ver o diagrama inteiro.

O cliente chama voar() confiando no contrato; o Pinguim herda o método mas não consegue cumpri-lo — a hierarquia está errada.

De onde vem

Barbara Liskov (Turing Award 2008) e Jeannette Wing definiram em 1994 a subtipagem comportamental: o subtipo pode enfraquecer pré-condições e fortalecer pós-condições, nunca o contrário, e precisa preservar as invariantes do tipo base.

Sintomas

  • Método sobrescrito que lança UnsupportedOperationException.
  • if (x is Subtipo) no código cliente para tratar um caso especial.
  • O clássico Quadrado que herda de Retângulo e quebra setLargura.

Como corrigir

Modele pelo comportamento, não pela taxonomia do mundo real: separe Ave de Voadora, ou use composição. Testes de contrato (os mesmos testes rodando contra todas as implementações) pegam a quebra cedo.

No código: antes e depois

✗ AntesKotlin
open class Ave { open fun voar() = println("voando") }
class Pinguim : Ave() {
  override fun voar() = throw UnsupportedOperationException()
}
fun migrar(aves: List<Ave>) = aves.forEach { it.voar() } // quebra com Pinguim
✓ DepoisKotlin
interface Ave { val nome: String }
interface Voadora : Ave { fun voar() }

class Pardal(override val nome: String = "pardal") : Voadora { override fun voar() = println("voando") }
class Pinguim(override val nome: String = "pinguim") : Ave

fun migrar(aves: List<Voadora>) = aves.forEach { it.voar() } // o tipo já garante

O compilador passa a impedir o erro: só quem realmente voa entra na lista de migração.

Em resumo

Referências

Continue aprendendo

Todos os temas de boas práticas e padrões →