Blueprints
Classes: construtores, herança, traits, polimorfismo, estáticos e sobrecarga de operadores.
Declarar#
Um blueprint é a classe do DataForge. Os parâmetros do cabeçalho viram campos automaticamente:
dataforge
blueprint Ponto(x, y):
action distancia():
yield sqrt(self.x ** 2 + self.y ** 2)
action toString():
yield $"({self.x}, {self.y})"
p := spawn Ponto(3, 4)
out p, p.x, p.distancia()saída
(3, 4) 3 5.0spawn instancia. forge é sinônimo, e chamar o blueprint diretamente (Ponto(3, 4)) também funciona.
Construtor com setup#
Para inicializar campos derivados, use o método setup:
dataforge
blueprint Pedido:
action setup(cliente):
self.cliente := cliente
self.itens := []
action adicionar(item):
self.itens.append(item)
yield len(self.itens)
p := spawn Pedido("Ana")
p.adicionar("mouse")As duas formas convivem: se um blueprint tem parâmetros e um setup, os parâmetros são atribuídos primeiro e depois o setup roda.
Herança#
dataforge
blueprint Animal(nome):
action falar():
yield "..."
action apresentar():
yield $"{self.nome} diz {self.falar()}"
blueprint Cachorro(nome) extends Animal:
action falar():
yield "Au au"
blueprint Gato(nome) extends Animal:
action falar():
yield "Miau"
cycle bicho in [spawn Cachorro("Rex"), spawn Gato("Mia")]:
out bicho.apresentar()saída
Rex diz Au au
Mia diz Miauapresentar está definido só no pai, mas chama self.falar() — que resolve para a versão do filho. Isso é polimorfismo.
root — chamar o pai#
dataforge
blueprint Base(nome):
action descrever():
yield $"Base:{self.nome}"
blueprint Derivada(nome) extends Base:
action descrever():
yield $"Derivada[{root.descrever()}]"
out (spawn Derivada("teste")).descrever()Traits#
Um trait declara um contrato. Um blueprint o compõe com with:
dataforge
trait Serializavel:
action serializar()
trait Comparavel:
action comparar(outro)
blueprint Produto(nome, preco) with Serializavel, Comparavel:
action serializar():
yield {"nome": self.nome, "preco": self.preco}
action comparar(outro):
yield self.preco - outro.precoMembros estáticos#
dataforge
blueprint Contador:
static total := 0
action inc():
Contador.total := Contador.total + 1
c := spawn Contador()
c.inc()
out Contador.total # 1 — compartilhado por todas as instânciasSobrecarga de operadores#
Defina os métodos com estes nomes e os operadores passam a funcionar:
| Método | Operador |
|---|---|
add | + |
sub | - |
mul | * |
div | / |
mod | % |
pow | ** |
floordiv | ~/ |
toString | out e str() |
setup / initiate | o construtor, chamado por spawn |
dataforge
blueprint Vetor(x, y):
action add(o):
yield spawn Vetor(self.x + o.x, self.y + o.y)
action mul(k):
yield spawn Vetor(self.x * k, self.y * k)
action toString():
yield $"<{self.x}, {self.y}>"
out spawn Vetor(1, 2) + spawn Vetor(3, 4) # <4, 6>
out spawn Vetor(1, 2) * 3 # <3, 6>Introspecção#
dataforge
p := spawn Ponto(3, 4)
out typeof(p) # Ponto
out class_name(p) # Ponto
out get_fields(p) # os campos da instância
out get_methods(p) # os métodos disponíveis
out has_method(p, "distancia")
out has_field(p, "x")
out get_mro(p) # ordem de resolução de métodosBlueprint ou record?#
Use record | Use blueprint |
|---|---|
| dados sem comportamento próprio | objetos com estado que muda |
| igualdade por valor | identidade importa |
| imutável | precisa mutar campos |
| sem herança | herança, traits, polimorfismo |
Detalhes em Records.