Traits
Contratos de interface compostos com with.
Declarar#
dataforge
trait Serializavel:
action serializar()
trait Comparavel:
action comparar(outro)Um trait lista assinaturas — ações sem corpo. Ele descreve o que um tipo deve saber fazer.
Compor#
dataforge
blueprint Produto(nome, preco) with Serializavel, Comparavel:
action serializar():
yield {"nome": self.nome, "preco": self.preco}
action comparar(outro):
yield self.preco - outro.preco
a := spawn Produto("Mouse", 80)
b := spawn Produto("Teclado", 200)
out a.serializar()
out a.comparar(b) # -120Um blueprint pode compor vários traits: with A, B, C.
Métodos com corpo#
Um trait pode trazer implementação padrão. Ela só é usada se o blueprint não definir a própria:
dataforge
trait Descritivel:
action descrever():
yield $"<{typeof(self)}>" # padrão
blueprint Simples with Descritivel:
# herda descrever()
action nada():
yield void
blueprint Detalhado(nome) with Descritivel:
action descrever(): # sobrescreve
yield $"Detalhado: {self.nome}"A limitação atual#
Enquanto isso, quando a garantia importa, verifique em tempo de execução:
dataforge
action processar(item):
guard has_method(item, "serializar"), $"{typeof(item)} nao implementa Serializavel"
yield item.serializar()Trait ou herança?#
Use trait | Use extends |
|---|---|
| definir uma capacidade | especializar um tipo |
| vários tipos não relacionados | relação "é um tipo de" |
| compor várias capacidades | uma cadeia de especialização |
| sem estado compartilhado | reaproveitar campos e lógica |
Na dúvida: se você diria "um Produto é um Serializável", talvez seja herança. Se diria "um Produto sabe serializar", é trait.
Introspecção#
dataforge
out has_method(a, "serializar") # yes
out get_methods(a) # todos os métodos disponíveis
out get_mro(a) # ordem de resolução