OK, espero que seja uma pergunta subjetiva o suficiente para programadores, mas aqui vai. Estou continuamente ampliando meu conhecimento de linguagens e práticas de engenharia de software ... e encontrei algo que simplesmente não faz sentido para mim.
No C ++, as declarações de classe incluem private:
métodos e parâmetros no arquivo de cabeçalho, que, teoricamente, é o que você passa ao usuário para incluir se você criar uma lib.
No Objective-C, @interface
s fazem praticamente a mesma coisa, forçando você a listar seus membros privados (pelo menos, há uma maneira de obter métodos particulares no arquivo de implementação).
Pelo que sei, Java e C # permitem fornecer uma interface / protocolo que pode declarar todas as propriedades / métodos acessíveis ao público e oferece ao codificador a capacidade de ocultar todos os detalhes de implementação no arquivo de implementação.
Por quê? O encapsulamento é um dos princípios principais do POO, por que o C ++ e o Obj-C não possuem essa capacidade básica? Existe algum tipo de prática recomendada para o Obj-C ou C ++ que oculta toda a implementação?
Obrigado,
fonte
Respostas:
A questão é se o compilador precisa saber o tamanho de um objeto. Nesse caso, o compilador precisa conhecer os membros privados para contá-los.
Em Java, existem tipos e objetos primitivos, e todos os objetos são alocados separadamente, e as variáveis que os contêm são realmente ponteiros. Portanto, como um ponteiro é um objeto de tamanho fixo, o compilador sabe o tamanho da coisa que uma variável representa, sem saber o tamanho real do objeto apontado. O construtor lida com tudo isso.
No C ++, é possível ter objetos representados localmente ou no heap. Portanto, o compilador precisa saber qual o tamanho de um objeto, para que ele possa alocar uma variável ou matriz local.
Às vezes, é desejável dividir a funcionalidade da classe em uma interface pública e em todo o resto privado, e é aí que a técnica PIMPL (Ponteiro para IMPLementação) entra. A classe terá um ponteiro para uma classe de implementação privada, e os métodos da classe pública podem chamar naquela.
fonte
Devido ao design do C ++, para criar um objeto na pilha, o compilador deve saber o tamanho dele. Para fazer isso, ele precisa ter todos os campos presentes no arquivo de cabeçalho, pois é tudo o que o compilador pode ver quando o cabeçalho é incluído.
Por exemplo, se você definir uma classe
então
sizeof(Foo)
ésizeof(a) + sizeof(b)
. Se houvesse algum mecanismo para separar os campos particulares, o cabeçalho poderia contercom
sizeof(Foo) = sizeof(a) + ???
.Se você realmente deseja ocultar dados privados, tente o idioma pimpl, com
no cabeçalho e uma definição
FooImpl
apenas paraFoo
o arquivo de implementação.fonte
Tudo isso se resume à escolha do design.
Se você realmente deseja ocultar os detalhes de implementação privada da classe C ++ ou Objective-C, fornece uma ou mais interfaces suportadas pela classe (classe virtual pura em C ++, Objective-C @protocol) e / ou cria a classe capaz de se construir, fornecendo um método de fábrica estático ou um objeto de fábrica de classe.
A razão pela qual as variáveis particulares são expostas no cabeçalho do arquivo / declaração de classe / @ interface é que um consumidor de sua classe talvez seja necessário criar uma nova instância do mesmo e um
new MyClass()
ou[[MyClass alloc]init]
no código do cliente precisa o compilador para entender o quão grande MyClass um objeto está em ordem para fazer a alocação.Java e C # também têm suas variáveis privadas detalhadas na classe - elas não são exceção a isso, mas na IMO o paradigma da interface é muito mais comum com essas linguagens. Você pode não ter o código fonte em cada caso, mas há metadados suficientes no código compilado / byte para deduzir essas informações. Como C ++ e Objective-C não possuem esses metadados, a única opção são os detalhes reais da interface class / @. No mundo C ++ COM, você não expõe as variáveis privadas de nenhuma classe, mas pode fornecer o arquivo de cabeçalho - porque a classe é totalmente virtual. Um objeto de fábrica de classe também é registrado para criar as instâncias reais e existem alguns metadados de várias formas.
Em C ++ e Objective-C, é menos trabalhoso distribuir o arquivo de cabeçalho comparado à gravação e manutenção de um arquivo de interface / protocolo adicional. Esse é um dos motivos pelos quais você vê a implementação privada exposta com tanta frequência.
Outro motivo no C ++ são os modelos - o compilador precisa conhecer os detalhes da classe para gerar uma versão dessa classe especializada nos parâmetros fornecidos. O tamanho dos membros da classe varia com a parametrização, portanto, é necessário ter essas informações.
fonte