Creo que C está perfectamente bien y es decente para implementar conceptos orientados a objetos, encogiéndose de hombros . La mayoría de las diferencias, según lo veo entre el subconjunto de denominador común de lenguajes considerados orientados a objetos, son menores y de naturaleza sintáctica desde mi punto de vista pragmático.
Comencemos con, por ejemplo, ocultando información. En C podemos lograrlo simplemente ocultando la definición de una estructura y trabajando con ella a través de punteros opacos. Eso efectivamente modela la distinción public
vs. private
de los campos de datos a medida que obtenemos con las clases. Y es bastante fácil de hacer y apenas es anti-idiomático, ya que la biblioteca estándar de C se basa en esto para lograr el ocultamiento de la información.
Por supuesto, pierde la capacidad de controlar fácilmente dónde se asigna la estructura en la memoria usando tipos opacos, pero eso es solo una diferencia notable entre, por ejemplo, C y C ++. C ++ es definitivamente una herramienta superior cuando compara su capacidad para programar conceptos orientados a objetos sobre C mientras mantiene el control sobre los diseños de memoria, pero eso no significa necesariamente que Java o C # sea superior a C en ese sentido, ya que esos dos lo hacen pierde completamente la capacidad de controlar dónde se asignan los objetos en la memoria.
Y tenemos que usar una sintaxis como fopen(file, ...); fclose(file);
en lugar de file.open(...); file.close();
pero big whoop. ¿A quien le importa? Tal vez solo alguien que se inclina fuertemente en la finalización automática en su IDE. Admito que puede ser una característica muy útil desde un punto de vista práctico, pero tal vez no sea una que requiera una discusión sobre si un idioma es adecuado para la POO.
No tenemos la capacidad de implementar efectivamente los campos protected
. Me someteré totalmente allí. Pero no creo que haya una regla concreta que diga: " Todos los idiomas OO deberían tener una función para permitir que las subclases accedan a miembros de una clase base a la que aún no deberían acceder los clientes normales ". Además, rara vez veo casos de uso para miembros protegidos que no desconfían en lo más mínimo de convertirse en un obstáculo de mantenimiento.
Y, por supuesto, tenemos que "emular" el polimorfismo OO con tablas de punteros de función y punteros a ellos para un envío dinámico con un poco más de repetitivo para inicializar los analógicos vtables
y vptrs
, pero un poco de repetitivo nunca me causó mucho dolor.
La herencia es muy similar. Podemos modelarlo fácilmente a través de la composición, y en el funcionamiento interno de los compiladores se reduce a lo mismo. Por supuesto, perdemos la seguridad de tipos si queremos reducir , y allí diría que si quieres reducir a la baja en absoluto, por favor no utilices C porque no Las cosas que las personas hacen en C para emular a downcasting pueden ser horribles desde el punto de vista de la seguridad de tipo, pero prefiero que las personas no bajen en absoluto. La seguridad de tipos es algo que puede comenzar a perder fácilmente en C, ya que el compilador proporciona tanto margen de maniobra para interpretar las cosas como bits y bytes, sacrificando la posibilidad de detectar posibles errores en tiempo de compilación, pero algunos lenguajes considerados orientados a objetos no son ni siquiera estático.
No lo sé, creo que está bien. Por supuesto, no usaría C para intentar crear una base de código a gran escala que se ajuste a los principios de SOLID, pero no es necesariamente debido a sus limitaciones en el frente orientado a objetos. Muchas de las funciones que echaría de menos si intentara usar C para tal propósito estarían relacionadas con las características del idioma que no se consideran directamente un requisito previo para la POO, como la seguridad de tipo fuerte, los destructores que se invocan automáticamente cuando los objetos quedan fuera del alcance, el operador sobrecarga, plantillas / genéricos y manejo de excepciones. Es cuando me pierdo las funciones auxiliares que utilizo para C ++.