Herança e traits
Estender sem reimplementar, e o que final impede.
`root` chama o pai#
blueprint Documento:
titulo: String := ""
action setup(titulo):
self.titulo := titulo
action cabecalho():
yield $"# {self.titulo}"
action render():
yield self.cabecalho()
blueprint Artigo extends Documento:
autor: String := ""
action setup(titulo, autor):
self.titulo := titulo
self.autor := autor
// acrescenta ao do pai, em vez de refazer
action cabecalho():
yield root.cabecalho() + $"\npor {self.autor}"É o que distingue estender de reimplementar: o filho acrescenta, e continua acompanhando as mudanças do pai.
Polimorfismo sem marcação#
Um método herdado que chama self.x() resolve para a versão do filho. No exemplo acima, render foi herdado sem mudança e usa o cabecalho sobrescrito.
`final`#
blueprint Base:
final action identidade():
yield self._idImpede a sobrescrita, e a tentativa falha na declaração do herdeiro:
erro[DF0301]: 'Filho.identidade' cannot override 'Base.identidade', which is declared finalUse no que o resto da hierarquia depende para funcionar — um método que outros métodos do pai chamam esperando um comportamento específico.
Traits#
trait Serializavel:
action serializar() // exigência
action salvar_em(caminho): // padrão, herdado
adopt Arcane.IO as IO
IO.write(caminho, self.serializar())
blueprint Config with Serializavel:
action serializar():
yield "…"Trait não guarda estado — por isso with aceita vários sem o problema clássico de herança múltipla.
Quando não herdar#
Herança amarra o filho ao pai para sempre. Antes de estender, pergunte se não é composição:
- Herança quando A é um B — um Artigo é um Documento
- Composição quando A tem um B — um Carro tem um Motor
Uma cadeia com mais de dois ou três níveis costuma ser sinal de que a modelagem foi longe demais. Veja modelagem.