Bien, espero que esta sea una pregunta suficientemente subjetiva para los programadores, pero aquí va. Continuamente estoy ampliando mi conocimiento de idiomas y prácticas de ingeniería de software ... y me he encontrado con algo que no tiene ningún sentido para mí.
En C ++, las declaraciones de clase incluyen private:
métodos y parámetros en el archivo de encabezado, que, en teoría, es lo que le pasa al usuario para que lo incluya si lo convierte en una biblioteca.
En Objective-C, @interface
hacemos prácticamente lo mismo, obligándote a enumerar tus miembros privados (al menos, hay una manera de obtener métodos privados en el archivo de implementación).
Por lo que puedo decir, Java y C # le permiten proporcionar una interfaz / protocolo que puede declarar todas las propiedades / métodos de acceso público y le da al codificador la capacidad de ocultar todos los detalles de implementación en el archivo de implementación.
¿Por qué? La encapsulación es uno de los principios principales de OOP, ¿por qué C ++ y Obj-C carecen de esta capacidad básica? ¿Existe algún tipo de mejor práctica para Obj-C o C ++ que oculte toda la implementación?
Gracias,
fuente
Respuestas:
La pregunta es si el compilador necesita saber qué tan grande es un objeto. Si es así, entonces el compilador tiene que saber acerca de los miembros privados para contarlos.
En Java, hay tipos y objetos primitivos, y todos los objetos se asignan por separado, y las variables que los contienen son realmente punteros. Por lo tanto, dado que un puntero es un objeto de tamaño fijo, el compilador sabe cuán grande representa una variable, sin conocer el tamaño real del objeto señalado. El constructor maneja todo eso.
En C ++, es posible tener objetos representados localmente o en el montón. Por lo tanto, el compilador necesita saber qué tan grande es un objeto, para poder asignar una variable o matriz local.
A veces es deseable dividir la funcionalidad de la clase en una interfaz pública y una privada todo lo demás, y ahí es donde entra en juego la técnica PIMPL (puntero a IMPLementation). La clase tendrá un puntero a una clase de implementación privada, y los métodos de la clase pública pueden llamar ese.
fuente
Debido al diseño de C ++, para crear un objeto en la pila, el compilador debe saber qué tan grande es. Para hacer esto, debe tener todos los campos presentes en el archivo de encabezado, ya que eso es todo lo que el compilador puede ver cuando se incluye el encabezado.
Por ejemplo, si define una clase
entonces
sizeof(Foo)
essizeof(a) + sizeof(b)
. Si hubiera algún mecanismo para separar los campos privados, entonces el encabezado podría contenercon
sizeof(Foo) = sizeof(a) + ???
.Si realmente quieres ocultar datos privados, prueba el modismo de pimpl, con
en el encabezado y una definición para
FooImpl
solo enFoo
el archivo de implementación.fuente
Todo esto se reduce a la elección del diseño.
Si realmente desea ocultar los detalles de la implementación privada de la clase C ++ u Objective-C, puede proporcionar una o más interfaces que la clase admita (clase virtual pura C ++, Objective-C @protocol) y / o crear la clase capaz de construirse proporcionando un método de fábrica estático o un objeto de fábrica de clase.
La razón por la que las variables privadas están expuestas en el archivo de encabezado / declaración de clase / interfaz @ es que un consumidor de su clase podría necesitar crear una nueva instancia de la misma y a
new MyClass()
o[[MyClass alloc]init]
en el código del cliente necesita el compilador para comprender qué tan grande es MyClass objeto es para hacer la asignación.Java y C # también tienen sus variables privadas detalladas en la clase, no son una excepción a esto, pero en mi opinión, el paradigma de la interfaz es mucho más común con esos lenguajes. Es posible que no tenga el código fuente en cada caso, pero hay suficientes metadatos en el código compilado / byte para deducir esta información. Como C ++ y Objective-C no tienen estos metadatos, la única opción son los detalles reales de la interfaz class / @. En el mundo COM de C ++, no expone las variables privadas de ninguna clase, pero puede proporcionar el archivo de encabezado, porque la clase es puramente virtual. También se registra un objeto de fábrica de clase para crear las instancias reales, y hay algunos metadatos en varias formas.
En C ++ y Objective-C, es menos trabajo distribuir el archivo de encabezado en comparación con escribir y mantener una interfaz adicional / @ archivo de protocolo. Esta es una razón por la que ve la implementación privada expuesta tan a menudo.
Otra razón en C ++ son las plantillas: el compilador necesita conocer los detalles de la clase para generar una versión de esa clase especializada para los parámetros proporcionados. El tamaño de los miembros de la clase variaría con la parametrización, por lo que debe tener esta información.
fuente