MRO — ordem de resolução
Com herança múltipla, qual método ganha. Linearização C3.
Quando um blueprint herda de um pai, a busca de método é óbvia: ele, depois o pai, depois o avô. Com herança múltipla não é — e a MRO (method resolution order) é a lista que responde, calculada por linearização C3, a mesma do Python.
blueprint A:
action quem():
yield "A"
blueprint B extends A:
action quem():
yield "B"
blueprint C extends A:
action quem():
yield "C"
blueprint D extends B, C:
action de_quem_herdo():
yield "de B e de C"
// D não declara 'quem': a MRO decide qual das duas responde
out (spawn D()).quem() // "B" — a MRO é D, B, C, AAs três garantias do C3#
- A classe vem antes das mães.
Dantes deBeC. - A ordem em que as mães foram escritas é respeitada.
extends B, CpõeBantes deC. - Uma mãe só aparece depois de todas as filhas dela.
Avem por último, mesmo sendo mãe deB.
Quando não existe ordem que satisfaça as três, a hierarquia é ambígua — e aí o C3 recusa, em vez de escolher em silêncio:
blueprint X extends A, B:
// se B já herda de A, esta ordem se contradiz
erro: cannot linearize the hierarchy of 'X'Recusar é o certo: uma escolha arbitrária aqui vira um bug que só aparece quando alguém acrescenta um método meses depois.
`root` segue a MRO#
root.metodo() não vai ao "primeiro pai": vai ao próximo na MRO, a partir de onde a chamada está. É o que faz uma cadeia de root percorrer cada blueprint exatamente uma vez, mesmo em diamante.
blueprint B extends A:
action quem():
yield "B->" + root.quem()
assert (spawn B()).quem() is "B->A"Quando ela é calculada#
Uma vez, na primeira consulta, e guardada. O C3 não é caro, mas a linhagem é percorrida em toda busca de método mágico — e aí a conta apareceria.