A resposta é ... bem ... simples. Simplicidade e consistência, de fato.
O Objective-C é puramente dinâmico no momento do envio do método. Em particular, todo envio de método passa exatamente pelo mesmo ponto de resolução de método dinâmico que qualquer outro envio de método. No tempo de execução, toda implementação de método tem exatamente a mesma exposição e todas as APIs fornecidas pelo tempo de execução Objective-C que funcionam com métodos e seletores funcionam igualmente da mesma forma em todos os métodos.
Como muitos responderam (aqui e em outras perguntas), os métodos privados em tempo de compilação são suportados; se uma classe não declarar um método em sua interface disponível ao público, esse método também pode não existir no que diz respeito ao seu código. Em outras palavras, você pode obter todas as várias combinações de visibilidade desejadas no momento da compilação, organizando seu projeto adequadamente.
Há pouco benefício em duplicar a mesma funcionalidade no tempo de execução. Isso acrescentaria uma quantidade enorme de complexidade e sobrecarga. E mesmo com toda essa complexidade, ainda assim não impediria que todos, exceto o desenvolvedor mais casual, executassem seus métodos supostamente "privados".
EDIT: Uma das suposições que notei é que as mensagens privadas teriam que passar pelo tempo de execução, resultando em uma sobrecarga potencialmente grande. Isso é absolutamente verdade?
Sim, ele é. Não há razão para supor que o implementador de uma classe não queira usar todo o recurso Objective-C definido na implementação, e isso significa que o envio dinâmico deve acontecer. No entanto , não há nenhuma razão específica para que métodos privados não possam ser despachados por uma variante especial de objc_msgSend()
, uma vez que o compilador saberia que eles eram privados; isto é, pode ser conseguido adicionando uma tabela de método somente privada à Class
estrutura.
Não haveria maneira de um método privado causar um curto-circuito nessa verificação ou pular o tempo de execução?
Não foi possível pular o tempo de execução, mas o tempo de execução não precisaria necessariamente verificar os métodos privados.
Dito isto, não há razão para que terceiros não possam deliberadamente chamar objc_msgSendPrivate()
um objeto, fora da implementação desse objeto, e algumas coisas (KVO, por exemplo) teriam que fazer isso. Com efeito, seria apenas uma convenção e pouco melhor na prática do que prefixar os seletores de métodos privados ou não mencioná-los no cabeçalho da interface.
Fazer isso, porém, minaria a pura natureza dinâmica da linguagem. Todo envio de método não passaria mais por um mecanismo de envio idêntico. Em vez disso, você ficaria em uma situação em que a maioria dos métodos se comporta de uma maneira e um pequeno punhado é apenas diferente.
Isso se estende além do tempo de execução, pois existem muitos mecanismos no cacau construídos sobre o dinamismo consistente do Objective-C. Por exemplo, tanto a codificação de valores-chave quanto a observação de valores-chave precisariam ser muito modificadas para dar suporte a métodos privados - provavelmente criando uma brecha explorável - ou métodos privados seriam incompatíveis.