Method Dispatch refere-se ao mecanismo que determina qual implementação deve ser utilizada quando um método é chamado.
Conhecer como o dispatch trabalha é necessário para escrever código performático e pode ajudar a entender alguns comportamentos confusos do Swift.
Static Dispatch
Static Dispatch, ou Direct Dispatch, é suportado tanto por tipos de valor quanto por tipos de referência.
Se um método é despachado estaticamente, o compilador pode localizar onde as instruções estão em tempo de compilação , sendo assim quando a função é chamada o sistema vai diretamente ao endereço de memória onde a função está armazenada para realizar a operação.
Esse comportamento resulta em uma execução muito rápida e permite que o compilador realize vários tipos de otimizações (devirtualization).
Exemplos
Struct
e enum
são tipo de valores que não suportam herança, portanto todos os métodos são do tipo static.
Métodos que não são definidos no contrato de um protocolo mas fazem parte da sua extensão são do tipo estático.
Dynamic Dispatch
É suportado somente por tipos de referência, ou classes, já que são tipos que suportam herança.
Apesar de static dispatch ser leve e rápido é limitado. Devido principalmente ao polimorfismo, uma grande quantidade de linguagens OOP suportam o dynamic dispatch.
Em Swift existem duas formas de dynamic dispatch:
Table dispatch
Com esse método uma classe é associada a uma tabela virtual que consiste de um array de ponteiros para a implementação real correspondente para a classe.
Cada classe possui sua cópia da tabela com ponteiros para cada método que foi feito o override
. Assim a cada chamada a um método o compilador precisa verificar, em tempo de execução, as implementações desse método em uma tabela virtual (witness table) e determinar se a chamada se refere a implementação da superclass ou da subclass.
Como o compilador precisar ler o endereço de memória da implementação e pular para esse endereço correspondente, o d_ynamic dispatch_ é um pouco mais lento que o static dispatch.
Message dispatch
Esse é um tipo de dispatch fornecido pelo Objective-C e o Swift usa a runtime lib do Objective-C para fazer a procura pela implementação correta.
Diferente do tabela virtual do table dispatch o dicionário de mensagens pode ser alterado em tempo de execução , o que possibilita alterar a funcionalidade de um método (method swizzling). Isso pode ser custoso, apesar de usar um mecanismo de cache, já que quando um método é chamado o runtime do Objective-C precisa passar pela hierarquia de classes para determinar qual implementação do método chamar.
O message dispatch é muito usado nos frameworks Cocoa , como KVO , Core Data e UIAppearance . Caso queira saber mais esse post apresenta vários detalhes técnicos.
Exemplos
A partir do Swift 4.0 precisamos marcar explicitamente que queremos expor nosso método para o Objective-C runtime.
Quando uma classe não terá subclasses podemos marcar ela como final, isso faz com que seus métodos usem o static dispatch.
Bom, é isso!
A ideia desse artigo era falar um pouco sobre um assunto mais técnico em português, já que a grande maioria do material encontrado é em inglês.
Espero que o artigo tenha sido útil e qualquer crítica, sugestão ou melhoria é só comentar.
Caso queira ler os artigos originais em que esse texto foi baseado são:
Top comments (0)