O despacho de método é um algoritmo usado para selecionar o método apropriado que precisa ser invocado durante uma chamada. O objetivo principal do despacho de método é fornecer ao programa informações sobre onde encontrar o código executável para um método específico na memória.
Linguagens compiladas têm três tipos de despacho de método:
O despacho estático é o método de despacho mais rápido em Swift. Como não há sobreposição de método disponível, existe apenas uma implementação do método, e ela reside em um único local na memória.
\ Podemos usar despacho estático usando palavras-chave como static, final, private.
\ O despacho estático é um despacho de método padrão para os tipos de valor, já que os tipos de valor não podem ser sobrepostos.
\ Vamos ver alguns exemplos:
Quando adicionamos a palavra-chave final a uma classe, seus métodos não suportam sobreposição, e é aí que o despacho estático entra em ação.
// MARK: Final class final class ClassExample { // MARK: Static dispatch func method() { // implementation ... } }
Quando você adiciona uma implementação padrão de um protocolo usando uma extensão, seu método de despacho muda para despacho estático em vez de usar uma Tabela de Testemunha.
// MARK: Prorocol Extension extension ProtocolExample { // MARK: Direct Dispatch func method() { // implementation ... } } class ClassExample2: ProtocolExample {} let classExample2 = ClassExample2() classExample2.method()
Quando um método é implementado em uma extensão, significa que não pode ser sobreposto por subclasses. Neste caso, há espaço para despacho estático.
// MARK: Example Class Extension class ClassExample3 {} extension ClassExample3 { // MARK: Direct Dispatch func method() { // implementation ... } } let classExample3 = ClassExample3() classExample3.method()
Não podemos acessar um método privado fora do corpo da classe. Isso significa que o método não pode ser sobreposto e usa despacho estático.
// MARK: Access Control class ClassExample4 { // MARK: Direct Dispatch private func method() { // implementation ... } }
O despacho de tabela é usado quando temos que lidar com herança. Este é um tipo padrão de despacho usado em Swift.
Para cada instância de uma classe ou subclasse, uma tabela virtual é criada que contém informações sobre métodos implementados para cada classe e armazena uma referência à implementação apropriada. A principal desvantagem do despacho de tabela virtual é que tem uma velocidade menor que o despacho estático.
\ Vamos ver um exemplo:
// MARK: Virtual Table class ParentClass { func method1() {} func methdod2() {} } class ChildClass: ParentClass { override func method1() {} func method3() {} }
\ Para cada instância, sua própria tabela virtual é criada da seguinte forma:
\
Uma Tabela de Testemunha é usada por protocolos e é criada para cada classe que está em conformidade com o protocolo. A CPU usa esta tabela para determinar onde deve procurar uma implementação apropriada. Cada tipo (valor e referência) que está em conformidade com um protocolo tem sua própria Tabela de Testemunha de Protocolo, que contém ponteiros para os métodos do tipo exigidos pelo protocolo.
\ Vamos ver um exemplo:
// MARK: Witness Table Dispatch protocol ProtocolExample { func method1() func method2() } class ClassExample1: ProtocolExample { func method1() {} func method2() {} } class ClassExample2: ProtocolExample { func method1() {} func method2() {} }
\ Neste caso, uma tabela de testemunha é criada para cada classe:
\
O Despacho de Mensagem é o estilo de despacho de método mais dinâmico. Ele procura uma implementação apropriada durante o tempo de execução. Como opera durante o tempo de execução, podemos usar o Method Swizzling para alterar implementações de métodos.
\ Se quiser usar o despacho de mensagem, precisa adicionar @objc dynamic antes de uma implementação de método.
// MARK: Message Dispatch class ClassExample: NSObject { @objc dynamic func method() {} } class SubClassExample: ClassExample { @objc dynamic override func method() {} } let subclass = SubClassExample() subclass.method()
\ A implementação do método é procurada dentro de SubClassExample. Se não houver implementação deste método nessa classe, a busca continua na classe pai, e assim por diante até chegar a NSObject.
\
Vamos combinar todos os tipos em uma única tabela:
\
Em resumo, o despacho de método em Swift é um aspecto crítico da execução de código, impactando o desempenho e a flexibilidade. Ao escolher o método de despacho certo, os desenvolvedores podem otimizar seu código, garantir adaptabilidade e aproveitar efetivamente os recursos dinâmicos do Swift. Compreender e dominar o despacho de método é essencial para construir aplicações Swift eficientes e adaptáveis.


