Pular para o conteúdo

Metaclasses

meta blueprint e using: interceptar a criação de classes, a construção de objetos e o acesso a membros, com ganchos de nome fixo.

Uma metaclasse é o blueprint que governa como outros blueprints nascem e se comportam. Em DataForge ela é um meta blueprint, aplicado com using, e fala com a linguagem por ganchos de nome fixo — um on_… desconhecido é recusado com sugestão, porque um gancho com nome errado nunca rodaria e nada avisaria.

GanchoQuandoDevolver algo
on_forge(molde)o blueprint acabou de ser montadosubstitui o blueprint
on_extend(mae, filha)um blueprint governado ganhou filha
on_spawn(molde, args)antes de construirentrega esse objeto no lugar
on_ready(obj)o objeto nasceu, invariantes conferidas
on_read(obj, nome, valor)toda leitura de membrotroca o valor lido
on_missing(obj, nome)leitura de membro que não existeé o valor lido
on_write(obj, nome, valor)toda escrita de campotroca o valor gravado
on_call(obj, nome, args)chamada de método vinda de fora
on_serialize(obj, vault)Objetos.para_vaultsubstitui o vault
on_deserialize(molde, vault)Objetos.de_vaultsubstitui o vault

Registro automático de classes#

dataforge
adopt Arcane.Reflexo as R

meta blueprint Registro:
    tabelas := {}
    action on_forge(molde):
        self.tabelas[R.nome(molde)] := R.nome(molde).lower() + "s"

blueprint Entidade using Registro:
    id := 0

blueprint Usuario extends Entidade:
    nome := ""

blueprint Pedido extends Entidade:
    total := 0

reg := R.meta_instancia(Pedido)
assert reg.tabelas["Usuario"] is "usuarios"
assert len(reg.tabelas) is 3

A metaclasse é herdada: Usuario não escreve using, e é governado. Ela tem uma instância só, compartilhada por tudo que governa — é o self dos ganchos e onde ela guarda estado.

Validar a classe na declaração#

dataforge
adopt Arcane.Reflexo as R

meta blueprint ComId:
    action on_forge(molde):
        nomes := [c["nome"] cycle c in R.campos(molde)]
        given not ("id" in nomes):
            trigger $"{R.nome(molde)} precisa de um campo 'id'"

blueprint Cliente using ComId:
    id := 0

monitor:
    blueprint Rascunho using ComId:
        texto := ""
    assert no
handle Error as e:
    assert "precisa de um campo" in e.message

Instanciação controlada e auditoria#

dataforge
meta blueprint Auditado:
    escritas := []
    unicos := {}
    action on_write(obj, nome, valor):
        self.escritas.append(nome)
    action on_spawn(molde, args):
        yield void            // void: constrói normalmente

blueprint Config using Auditado:
    porta := 80
    action trocar(p):
        self.porta := p

c := spawn Config()
c.trocar(8080)
c.porta := 9090
assert c.porta is 9090