Esta será una pregunta muy poco técnica y no técnica, y no estoy seguro de si esta es la plataforma correcta. Pero soy un estudiante principiante de CS, así que espero que lo toleren.
En el primer semestre, nos presentaron conceptos OOP como encapsulación, ocultación de datos, modularidad, herencia, etc. a través de Java y UML. (Java es mi primer lenguaje de programación)
Según tengo entendido, OOP es una forma de gestionar la complejidad del software. Pero sus principios no son nuevos ni únicos, son en cierto sentido universales para todos los campos de ingeniería.
Por ejemplo, un automóvil es una estructura muy compleja cuya complejidad es manejada por una jerarquía de componentes modulares y encapsulados con comportamientos e interfaces bien definidos.
Pero no entiendo la razón detrás de la introducción de un nuevo paradigma de programación. Creo que todos los principios utilizados para gestionar la complejidad pueden realizarse mediante lenguajes de programación de procedimientos. Por ejemplo, para modularidad, podemos dividir el programa en muchos programas pequeños que realizan tareas bien definidas cuyo código está contenido en archivos separados. Estos programas interactuarían entre sí a través de sus entradas y salidas bien definidas. Los archivos pueden estar protegidos (¿cifrados?) Para lograr la encapsulación. Para la reutilización del código, podemos llamar a esos archivos siempre que sean necesarios en nuevos programas. ¿Esto no captura todo lo que es OOP o me estoy perdiendo algo muy obvio?
No estoy pidiendo una prueba de que OOP maneja la complejidad. En mi opinión, ciertamente lo hace. Pero creo que todos los principios utilizados para gestionar la complejidad, como la modularidad, la encapsulación, la ocultación de datos, etc., pueden implementarse muy fácilmente mediante lenguajes de procedimiento. Entonces, ¿por qué realmente OOP si podemos gestionar la complejidad sin ella?
fuente
Respuestas:
Déjame probar con una respuesta teórica realmente baja :)
Lo que realmente está preguntando es: ¿Por qué incluir soporte para la Orientación de Objetos (OO) directamente en el lenguaje cuando se pueden usar lenguajes de procedimiento para diseñar y escribir código OO?
Y la respuesta es: tener un estándar sobre cómo se expresa OO en el código fuente para no terminar con 22 implementaciones diferentes para la misma abstracción.
Por ejemplo, supongamos que creo una
MagicButton
y unaMagicSlider
que se puede utilizar en un sistema de interfaz de usuario. Necesito una forma de agrupar los métodos que pueden usarse con MagicButton, los métodos que solo pueden usarse con MagicSlider y los métodos que pueden usar ambos. Estos objetos comparten algunos métodos porque ambos son objetos Magic gui.Puedo agrupar nombrando funciones de una manera especial
MagicSlider_DoSomething ...
, incluyendo los métodos en archivos específicos nombrados de una manera especialMagicSliderMethods.XXX
, o podría encontrar alguna otra forma especial de hacer lo mismo. Si no hay una forma estándar en el idioma para hacerlo, lo haré diferente de usted y de cualquier otra persona. Esto hace que compartir código sea mucho más difícil.Sí, el envío tardío (métodos virtuales en lenguajes OO) puede implementarse en lenguajes de procedimiento, pero hay muchas formas diferentes de implementarlo. Dependiendo de quién escribió el código, terminará con diferentes implementaciones de OO dentro del mismo programa.
Piensa en el pobre desarrollador de mantenimiento. Esta persona debe administrar diferentes abstracciones de objetos y diferentes formas de llamar a métodos virtuales dependiendo de quién escribió el código original.
Además: tener las abstracciones en el lenguaje permite a los editores de código avanzados como Eclipse realizar muchos análisis estáticos en el código. Por ejemplo, Eclipse puede ofrecer una lista de todos los métodos que se pueden usar en un objeto, así como la implementación automática de "métodos TODO" vacíos. Eclispe sabe exactamente qué métodos debe implementar su clase en función de qué clases extienda y qué interfaces implemente. Esto sería casi imposible si no hubiera un estándar de lenguaje para hacer OO.
fuente
Ninguno de esos son conceptos OOP. Todos existen fuera de OO, independientes de OO y muchos incluso fueron inventados antes de OO.
Entonces, si crees que de eso se trata OO, entonces tu conclusión es correcta: puedes hacer todo eso en lenguajes de procedimiento, porque no tienen nada que ver con OO .
Por ejemplo, uno de los documentos fundamentales sobre Modularidad es Sobre los criterios que se utilizarán en los sistemas de descomposición en módulos . No hay mención de OO allí. (Fue escrito en 1972, para entonces OO todavía era un nicho oscuro, a pesar de tener ya más de una década).
Si bien la abstracción de datos es importante en OO, es más una consecuencia de la característica principal de OO (Mensajería) que una característica definitoria. Además, es muy importante recordar que existen diferentes tipos de abstracción de datos. Los dos tipos más comunes de abstracción de datos que se usan actualmente (si ignoramos "ninguna abstracción", que probablemente todavía se usa más que las otras dos combinadas), son los tipos de datos abstractos y los objetos . Entonces, con solo decir "Ocultación de información", "Encapsulación" y "Abstracción de datos", no ha dicho nada sobre OO, ya que OO es solo una forma de abstracción de datos, y las dos son de hecho fundamentalmente diferentes:
Lo que esto significa, por cierto, es que en Java, las clases no están orientadas a objetos. Dos instancias de la misma clase pueden acceder mutuamente a la representación y la implementación privada. Por lo tanto, las instancias de clases no son objetos, de hecho son instancias ADT. Java
interface
s, sin embargo, no proporcionan la abstracción de datos orientada a objetos. En otras palabras: solo las instancias de interfaces son objetos en Java, las instancias de clases no lo son.Básicamente, para los tipos, solo puede usar interfaces. Esto significa tipos de parámetros de métodos y constructores, tipos de métodos de retorno, tipos de campos de instancia, campos estáticos y campos locales, el argumento para un
instanceof
operador o un operador de conversión, y los argumentos de tipo para un constructor de tipo genérico siempre deben ser interfaces. Una clase solo se puede usar directamente después delnew
operador, en ningún otro lugar.Lo que describe es OO.
De hecho, esa es una buena manera de pensar en OO. De hecho, eso es exactamente lo que los inventores originales de OO tenían en mente. (Alan Kay fue un paso más allá: imaginó muchas pequeñas computadoras que se enviaban mensajes entre sí a través de la red). Lo que llama "programa" generalmente se llama "objeto" y, en lugar de "llamar", generalmente decimos "envíe un mensaje ".
La orientación a objetos se trata de mensajería (también conocido como despacho dinámico ). El término "Orientado a objetos" fue acuñado por el Dr. Alan Kay, el diseñador principal de Smalltalk, y lo define así :
Analicemos eso:
En lo que respecta a la implementación, la mensajería es una llamada a un procedimiento con retraso, y si las llamadas a un procedimiento tienen un retraso, entonces no puede saber en tiempo de diseño a qué llamará, por lo que no puede hacer ninguna suposición sobre la representación concreta del estado. Entonces, realmente se trata de mensajes, el enlace tardío es una implementación de mensajes y la encapsulación es una consecuencia de ello.
Más tarde aclaró que " La gran idea es 'enviar mensajes' ", y lamenta haberlo llamado "orientado a objetos" en lugar de "orientado a mensajes", porque el término "orientado a objetos" pone el foco en lo que no es importante (objetos ) y distrae de lo que es realmente importante (mensajes):
(Por supuesto, hoy en día, la mayoría de las personas ni siquiera se enfocan en objetos sino en clases, lo cual es aún más incorrecto).
La mensajería es fundamental para OO, tanto como metáfora como mecanismo.
Si le envía un mensaje a alguien, no sabe qué hace con él. Lo único que puedes observar es su respuesta. No sabe si procesaron el mensaje ellos mismos (es decir, si el objeto tiene un método), si enviaron el mensaje a otra persona (delegación / representación), incluso si lo entendieron. De eso se trata la encapsulación, de eso se trata OO. Ni siquiera puede distinguir un proxy del real, siempre que responda como espera que lo haga.
Un término más "moderno" para "mensajería" es "despacho de método dinámico" o "llamada de método virtual", pero eso pierde la metáfora y se enfoca en el mecanismo.
Por lo tanto, hay dos formas de ver la definición de Alan Kay: si la mira por sí sola, puede observar que la mensajería es básicamente una llamada a un procedimiento vinculado de forma tardía y la vinculación tardía implica la encapsulación, por lo que podemos concluir que # 1 y # 2 son en realidad redundantes, y OO tiene que ver con la unión tardía.
Sin embargo, más tarde aclaró que lo importante es la mensajería, por lo que podemos verlo desde un ángulo diferente: la mensajería está retrasada. Ahora, si la mensajería fuera lo único posible, entonces el # 3 sería trivialmente cierto: si solo hay una cosa, y esa cosa está vinculada tarde, entonces todas las cosas están vinculadas tarde. Y una vez más, la encapsulación se deriva de la mensajería.
También se hacen puntos similares en On Understanding Data Abstraction, revisado por William R. Cook y también su Propuesta de definiciones modernas y simplificadas de "objeto" y "orientado a objetos" :
¡En Smalltalk-72, ni siquiera había ningún objeto! Había sólo flujos de mensajes que quedó analizando, reescrito y redireccionados. Primero llegaron los métodos (formas estándar de analizar y redirigir las secuencias de mensajes), luego vinieron los objetos (agrupaciones de métodos que comparten algún estado privado). La herencia llegó mucho más tarde, y las clases solo se introdujeron como una forma de apoyar la herencia. Si el grupo de investigación de Kay ya hubiera conocido los prototipos, probablemente nunca habrían introducido clases en primer lugar.
Benjamin Pierce en Tipos y lenguajes de programación argumenta que la característica definitoria de la Orientación a objetos es la recursión abierta .
Entonces: según Alan Kay, OO tiene que ver con la mensajería. Según William Cook, OO tiene que ver con el envío de métodos dinámicos (que es realmente lo mismo). Según Benjamin Pierce, OO se trata de Open Recursion, lo que básicamente significa que las autorreferencias se resuelven dinámicamente (o al menos esa es una forma de pensar) o, en otras palabras, mensajes.
Como puede ver, la persona que acuñó el término "OO" tiene una visión bastante metafísica de los objetos, Cook tiene una visión bastante pragmática y Pierce una visión matemática muy rigurosa. Pero lo importante es: ¡el filósofo, el pragmático y el teórico están de acuerdo! La mensajería es el único pilar de OO. Período.
¡Tenga en cuenta que aquí no se menciona la herencia! La herencia no es esencial para OO. En general, la mayoría de los lenguajes OO tienen alguna forma de reutilización de implementación, pero eso no necesariamente tiene que ser herencia. También podría ser alguna forma de delegación, por ejemplo. De hecho, el Tratado de Orlando analiza la delegación como una alternativa a la herencia y cómo las diferentes formas de delegación y herencia conducen a diferentes puntos de diseño dentro del espacio de diseño de los lenguajes orientados a objetos. (Tenga en cuenta que incluso en los lenguajes que admiten la herencia, como Java, a las personas se les enseña a evitarlo, lo que nuevamente indica que no es necesario para OO).
fuente
Cuando dices "muy fácilmente" estás haciendo una declaración muy audaz. La forma en que lo leo es: "No veo la dificultad, por lo que no debe ser muy grande". Cuando se formula de esa manera, queda claro que no estás preguntando "¿por qué necesitamos OO?", Estás preguntando "¿por qué las dificultades que otros paradigmas de programación encontraron que conducen a la invención de OO son inmediatamente aparentes para mí? "
Una respuesta a esa pregunta es que muchas de estas dificultades no existen en los tipos de programas en los que está trabajando. No se le pide que actualice el código de espagueti de 40 años. No está intentando escribir un nuevo administrador de pantalla para un sistema operativo. No está depurando aplicaciones distribuidas multiproceso.
Para muchos de los tipos de programas de juguetes que los estudiantes de CS tienen la tarea de escribir, podríamos escribirlos en BASIC o ensamblado como Java o Python. Esto se debe a que la complejidad inherente de las tareas es muy baja, solo hay un desarrollador, no hay problemas de interoperabilidad heredados, el rendimiento no importa y el código probablemente solo se ejecutará algunas veces en una máquina.
Imagínese tomar un conductor de estudiantes y pedirles que se unan en una calle concurrida en hora punta, en una transmisión manual sin sincronismo, en dirección a una colina empinada. Desastre. ¿Por qué? No pueden administrar el nivel de complejidad requerido para seguir simultáneamente todas las reglas que requiere la tarea.
Ahora imagine al mismo estudiante, el mismo vehículo, conduciendo a un ritmo de caminata en un estacionamiento vacío. Están bien, porque su nivel de habilidad es adecuado para la tarea. No hay presión, hay poco riesgo, y pueden tomar las subtareas individuales de arranque, embrague, cambio, aceleración, dirección, una a la vez.
Ese estudiante podría preguntar por qué tenemos transmisiones automáticas, si un conductor experto puede hacer todas estas cosas simultáneamente. La respuesta es que un conductor suficientemente hábil no necesita, en condiciones óptimas, una automática. Pero no todos somos conductores profesionales en óptimas condiciones y, por lo general, queremos la conveniencia de que los diseñadores de automóviles se encarguen de toda esa complejidad por nosotros.
Un programador hábil y disciplinado puede crear un sistema funcional de alta complejidad en C, o ensamblaje. Pero no todos somos Linus Torvalds. Tampoco deberíamos serlo, para crear software útil.
Personalmente, no me interesa tener que reinventar todas las características de un lenguaje moderno antes de que pueda abordar el problema en cuestión. Si puedo aprovechar un lenguaje que incluye soluciones a problemas ya resueltos, ¿por qué no lo haría?
Así que le daré la vuelta a su pregunta y le preguntaré si los idiomas ofrecen características convenientes como la encapsulación y el polimorfismo, ¿por qué no deberíamos usarlos?
fuente
Lo que estás describiendo no es OOP, es abstracción. La abstracción está presente en todos los modelos modernos de diseño, incluso en los que no son POO. Y OOP es un tipo muy específico de abstracción.
Primero, vale la pena señalar que no existe una definición única de OOP, por lo que puede haber personas que no estén de acuerdo con lo que yo caracterizo como OOP.
En segundo lugar, es importante recordar que OOP se inspiró en modelos de diseño tradicionales, por lo que las similitudes con el diseño de automóviles no son una coincidencia.
Sin embargo, aquí hay algunas formas en que la POO tiene más matices que lo que has dicho:
Encapsulación: no se trata solo de tener una interfaz establecida para un módulo (es decir, abstracción), se trata de prohibir el acceso más allá de esta interfaz. En Java, acceder a una variable privada es un error de compilación, mientras que en el diseño de su automóvil, puede (en algunos casos) usar las cosas de una manera diferente a la interfaz deseada.
Herencia: Esto es realmente lo que hace que la POO sea única. Una vez que haya definido una interfaz, puede hacer varias cosas implementando esa interfaz, y puede hacerlo de forma jerárquica, alterando partes específicas de su implementación, mientras hereda todas las partes anteriores, reduciendo enormemente la duplicación de código.
Si piensa en términos de los componentes encapsulados de un automóvil, no hay realmente un equivalente a esto. No hay una manera de hacer una marcha tomando una marcha diferente y cambiando una parte específica de su implementación. (Al menos no lo creo, no sé mucho sobre automóviles).
Polimorfismo : una vez que haya definido una interfaz, cualquier cosa que use esa interfaz debería ser indistinguible, desde el punto de vista de qué operaciones están disponibles, y no debería necesitar saber qué implementación se está utilizando para usar una interfaz. Aquí es donde el subtipo y el Principio de sustitución de Liskov se vuelven importantes.
Acoplamiento : Un aspecto clave de OOP es que relacionamos estrechamente las cosas con las mismas operaciones y distribuimos las diferentes formas que pueden tener. Los datos se agrupan con operaciones en esos datos. Esto significa que es muy fácil agregar una nueva forma de datos (una nueva implementación), pero muy difícil agregar una nueva operación a una interfaz (ya que tendría que actualizar cada clase que implementa la interfaz). Esto contrasta con los tipos de datos algebraicos en lenguajes funcionales, donde es muy fácil agregar una nueva operación (solo escribe una función que se ocupe de todos los casos), pero es difícil agregar una nueva variante (ya que necesita agregar una nueva caso a todas sus funciones).
fuente
Esto depende del significado de la palabra "necesidad".
Si "necesidad" significa requiere, no, no lo requerimos.
Si "necesidad" significa "proporciona fuertes beneficios", entonces diría "Sí", lo deseamos.
Cuadro grande
Los lenguajes OO vinculan la funcionalidad a los datos.
Puede evitar este enlace y funciones de escritura que pasan valores de datos.
Pero entonces probablemente terminará con constelaciones de datos que van juntas, y comenzará a pasar tuplas, registros o diccionarios de datos.
Y realmente, esas son todas las llamadas a métodos: funciones parciales en conjuntos de datos vinculados.
Característica por característica
Características de OOP:
Sin embargo, ninguna de esas cosas sucede tan fácilmente como con un lenguaje orientado a objetos con soporte de primera clase de esas características.
Referencias
Hay muchos críticos de OOP .
Sin embargo, los estudios parecen indicar que obtenemos una mayor productividad del programador a partir de la reutilización del código a través de OOP. Este es un hallazgo controvertido, y algunos investigadores dicen que no pueden reproducir estas ganancias de productividad, dadas ciertas restricciones. (fuente)
Conclusión
No "necesitamos" POO. Pero en algunos casos el usuario quiere OOP.
Tengo entendido que los programadores maduros pueden ser bastante productivos en el estilo orientado a objetos. Y cuando los paquetes tienen objetos centrales con interfaces simples que se entienden fácilmente, incluso los nuevos programadores pueden ser bastante productivos rápidamente.
fuente
Intentaré ser breve.
El principio central de OO es la combinación de datos y comportamiento en una sola unidad organizativa (un objeto).
Esto es lo que nos permite controlar la complejidad y fue un concepto bastante innovador cuando surgió. Compare eso con los archivos por un lado (datos puros), los programas que leen y procesan esos archivos por el otro lado (lógica pura) y la salida (datos puros nuevamente).
Solo una vez que tenga ese paquete de datos y lógica juntos, modelando alguna entidad del mundo real, puede comenzar a intercambiar mensajes, crear clases secundarias, separar datos y comportamientos privados de públicos, implementar comportamientos polimórficos, hacer toda esta magia específica de OO.
Entonces, sí, OO es un gran problema. Y no, no es solo un montón de cosas viejas con un nombre elegante.
Desmontarlo todo, mirar los elementos y luego decir "oh, bueno, aquí no hay nada que no haya visto antes" no es reconocer el ensamblaje que contiene la innovación. El resultado es más que la suma de sus partes.
fuente
No existe una definición "oficial" de programación orientada a objetos, y personas razonables no están de acuerdo con lo que realmente define la calidad de OO. Algunos dicen mensajes, algunos dicen subtipos, otros dicen herencia, algunos dicen la agrupación de datos y comportamiento. Eso no significa que el término no tenga sentido, solo que no debería quedar atrapado en disputas sobre lo que es OO real .
La encapsulación y la modularidad son principios más fundamentales del diseño y deben aplicarse en todos los paradigmas de programación. Los defensores de OO no afirman que estas propiedades solo se puedan lograr con OO, solo que OO es particularmente adecuado para lograr esto. Por supuesto, los defensores de otros paradigmas, como la programación funcional, afirman lo mismo para su paradigma. En la práctica, muchos lenguajes exitosos son multi-paradigmáticos y el OO, funcional, etc. debe ser visto como una herramienta más que como "la única forma verdadera".
Es cierto, porque al final puedes hacer cualquier cosa en cualquier lenguaje de programación. Puede ser más fácil en algunos idiomas que en otros, ya que todos los idiomas tienen diferentes fortalezas y debilidades.
fuente
Algo que las otras respuestas no han mencionado: estado.
Hablas de OO como una herramienta para gestionar la complejidad . ¿Qué es la complejidad? Ese es un término difuso. Todos tenemos este sentido gestalt de lo que significa, pero es más difícil precisarlo. Podríamos medir la complejidad ciclomática, es decir, el número de rutas de tiempo de ejecución a través del código, pero no sé de qué estamos hablando cuando usamos OO para gestionar la complejidad.
De lo que creo que estamos hablando es de la complejidad relacionada con el estado.
Hay dos ideas principales detrás de la encapsulación . Uno de ellos, la ocultación de los detalles de implementación , está bastante bien cubierto en las otras respuestas. Pero otro está ocultando su estado de tiempo de ejecución . No jugamos con los datos internos de los objetos; pasamos mensajes (o métodos de llamada si prefiere detalles de implementación sobre el concepto, como señaló Jörg Mittag). ¿Por qué?
La gente ya ha mencionado que es porque no puede cambiar la estructura interna de sus datos sin cambiar el código al que accede, y desea hacerlo en un lugar (el método de acceso) en lugar de 300 lugares.
Pero también es porque hace que el código sea difícil de razonar : el código de procedimiento (ya sea en un lenguaje de naturaleza procesal o simplemente escrito en ese estilo) ofrece poca ayuda para imponer restricciones a la mutación del estado. Cualquier cosa puede cambiar en cualquier momento desde cualquier lugar. Las funciones / métodos de llamada pueden tener acción a distancia espeluznante. Las pruebas automatizadas son más difíciles, ya que el éxito de las pruebas está determinado por el valor de las variables no locales a las que se accede / accede ampliamente.
Los otros dos grandes paradigmas de programación (OO y funcional) ofrecen soluciones interesantes, pero casi diametralmente opuestas, al problema de la complejidad relacionada con el estado. En la programación funcional, se intenta evitarlo por completo: las funciones son generalmente puras, las operaciones en estructuras de datos devuelven copias en lugar de actualizar el original en su lugar, etc.
OO, por otro lado, ofrece herramientas para manejar el estado de gestión (en lugar de herramientas para evitarlo). Además de las herramientas de nivel de lenguaje como modificadores de acceso (protegidos / públicos / privados), captadores y establecedores, etc., también hay una serie de convenciones relacionadas, como la Ley de Demeter, que aconseja no llegar a través de los objetos para obtener datos de otros objetos. .
Tenga en cuenta que no necesita objetos para hacer nada de esto: podría tener un cierre que tenga datos inaccesibles y devuelva una estructura de datos de funciones para manipularlos. ¿Pero no es eso un objeto? ¿No se ajusta eso a nuestra concepción de lo que es un objeto, intuitivamente? Y si tenemos este concepto, ¿no es mejor volver a aplicarlo en el lenguaje en lugar de (como han dicho otras respuestas) confiar en una explosión combinatoria de implementaciones ad-hoc en competencia?
fuente
No. Pero pueden ayudar en muchas situaciones.
He usado principalmente un solo lenguaje OO durante décadas, pero la mayor parte de mi código es en realidad estrictamente de procedimiento previo al estilo OO. Sin embargo, para cualquier cosa que involucre una GUI, utilizo la vasta biblioteca OO del lenguaje de métodos y objetos integrados, porque simplifica enormemente mi código.
Por ejemplo, una aplicación de Windows que usa la API original de Windows de bajo nivel para mostrar un formulario, un botón y un campo de edición requiere mucho código, mientras que en su lugar, usar las bibliotecas de objetos que vienen con Visual Basic o C # o Delphi hacen lo mismo programa pequeño y trivial. Por lo tanto, mi código OO suele ser relativamente pequeño y para la GUI, mientras que mi código que invocan esos objetos suele ser mucho más grande y generalmente no tiene que ver con ser OO (aunque puede variar según el problema que estoy tratando de resolver).
He visto programas OO que eran demasiado complicados, se basaban en reglas esotéricas complicadas sobre cómo se implementaron los objetos, y podrían haber sido mucho más simples si se escribieran sin conceptos OO. También he visto lo contrario: sistemas complejos que claman por ser reimplementados y simplificados mediante el uso de objetos.
A medida que gane experiencia, encontrará que diferentes situaciones requieren diferentes herramientas y soluciones, y un tamaño no sirve para todos.
fuente
Como alguien involucrado en un proyecto muy grande completamente escrito en C, definitivamente puedo decir que la respuesta es un claro "no".
La modularidad es importante. Pero la modularidad se puede implementar en prácticamente cualquier lenguaje decente. Por ejemplo, C admite compilación modular, archivos de encabezado y tipos de estructura. Esto es suficiente para el 99% de los casos. Defina un módulo para cada nuevo tipo de datos abstractos que necesite y defina las funciones para operar en el tipo de datos. A veces, desea rendimiento y esas funciones están en el archivo de encabezado como funciones en línea, otras veces utilizará funciones estándar. Todo es invisible para el usuario de qué manera se elige.
Estructura de soporte de la composición. Por ejemplo, puede tener una tabla hash bloqueada que consta de un bloqueo mutex y una tabla hash normal. Esto no es programación orientada a objetos; No se realiza ninguna subclasificación. La composición es una herramienta mucho más antigua que la idea de la programación orientada a objetos.
Para el 1% de los casos en los que la modularidad del nivel de compilación no es suficiente y necesita modularidad en tiempo de ejecución, existe una cosa llamada punteros de función. Permiten tener implementaciones individuales de una interfaz bien definida. Tenga en cuenta que esto no es programación orientada a objetos en un lenguaje no orientado a objetos. Esto es definir una interfaz y luego implementarla. Por ejemplo, la subclase no se usa aquí.
Considere quizás el proyecto de código abierto más complejo que existe. A saber, el kernel de Linux. Está escrito completamente en lenguaje C. Se realiza principalmente mediante el uso de herramientas de modularidad de nivel de compilación estándar, incluida la composición, y ocasionalmente, cuando se necesita modularidad en tiempo de ejecución, se utilizan punteros de función para definir e implementar una interfaz.
Si intenta encontrar un ejemplo de programación orientada a objetos en el kernel de Linux, estoy seguro de que encontrar ese ejemplo es muy difícil, a menos que extienda la programación orientada a objetos para incluir tareas estándar como "definir una interfaz y luego implementarla".
Tenga en cuenta que incluso el lenguaje de programación C admite la programación orientada a objetos si realmente lo necesita. Por ejemplo, considere el kit de herramientas de interfaz gráfica de usuario GTK. En realidad, está orientado a objetos, aunque esté escrito en un lenguaje no orientado a objetos. Entonces, esto muestra que la idea de que necesita un "lenguaje orientado a objetos" es profundamente defectuosa. No hay nada que un lenguaje orientado a objetos pueda hacer que otro tipo de lenguaje no pueda hacer. Además, si eres un programador experto, sabes cómo escribir código orientado a objetos en cualquier idioma con mucha facilidad. No es una carga usar C, por ejemplo.
Entonces, las conclusiones son que los lenguajes orientados a objetos probablemente sean útiles solo para programadores novatos que no entienden cómo se implementa realmente el concepto. Sin embargo, no quisiera estar cerca de ningún proyecto en el que los programadores sean programadores novatos.
fuente
La razón para introducir paradigmas de programación, incluidos los métodos orientados a objetos, es facilitar la creación de programas más sofisticados y potentes. En la edición de agosto de 1981 de la revista Byte, Daniel Ingalls , uno de los creadores clave de Smalltalk, definió "orientado a objetos" como la participación de las siguientes capacidades:
Estos fueron los principios que Ingalls identificó como las consideraciones de diseño de conducción para SmallTalk-80 desarrollado por Xerox Parc Research. En el artículo de la revista mencionado anteriormente, puede leer una descripción detallada de cada uno de estos principios y cómo contribuyen al paradigma orientado a objetos según Ingalls.
Todos estos principios se pueden aplicar utilizando cualquier lenguaje completo de Turing, ya sea de procedimiento, lenguaje ensamblador o lo que sea. Estos son principios de diseño, no una especificación de lenguaje. El objetivo de un lenguaje orientado a objetos es facilitar el uso de estos principios al crear software.
Por ejemplo, para tomar el primero de los principios de Ingall (administración automática de almacenamiento), cualquiera puede escribir su propio sistema automático de administración de almacenamiento en un lenguaje de procedimiento, pero sería mucho trabajo hacerlo. Cuando se utiliza un lenguaje como SmallTalk o Java que tiene integrada la administración automática de almacenamiento, el programador no tiene que hacer tanto trabajo para administrar la memoria. La desventaja es que el programador obtiene menos control sobre la forma en que se usa la memoria. Entonces, hay un beneficio y un inconveniente. La idea de un paradigma de diseño como la programación orientada a objetos es que los beneficios del paradigma superarán las desventajas para al menos algunos programadores.
fuente
Una forma de administrar la complejidad del software es separar el marco de las acciones deseadas por completo utilizando un lenguaje específico de dominio . Esto significa que el nivel de código de programación es distinto del nivel en el que se configuran los resultados deseados, un lenguaje o sistema completamente diferente. Cuando esto se hace correctamente, el código convencional se convierte esencialmente en una biblioteca, y el usuario u otra persona que crea los resultados deseados conecta todo junto con un lenguaje de script o una herramienta de diseño visual, como un generador de informes.
Para funcionar, esto requiere dibujar un límite estricto en torno a qué operaciones serán posibles y cómo se vinculan (lenguaje de script o diseño visual, como una herramienta de construcción de formularios). Los metadatos son una forma importante de abstraer la configuración del tiempo de ejecución de los detalles de codificación, haciendo posible que un sistema admita una amplia gama de resultados deseados. Si los límites se establecen y se mantienen (sin aceptar todas las solicitudes de extensión que se presenten), puede tener un sistema duradero y robusto que funcione para las personas, sin que tengan que ser programadores para lograr lo que quieren.
Martin Fowler ha escrito un libro sobre esto, y la técnica es casi tan antigua como la programación misma. Casi se podría decir que todos los lenguajes de programación son lenguajes específicos de dominio, por lo que la idea es endémica, pasada por alto porque es muy obvia. Pero aún puede crear sus propias herramientas de diseño visual o de secuencias de comandos para facilitarle la vida. ¡A veces, generalizar un problema hace que sea mucho más fácil de resolver!
fuente
Esta es una muy buena pregunta y siento que las respuestas dadas aquí no han hecho justicia, así que seguiré adelante y agregaré mis pensamientos.
El objetivo es: administrar la complejidad del software . El objetivo no es "usar lenguaje OO".
No hay "razón" para introducir un nuevo paradigma. Es algo que sucedió naturalmente cuando la codificación se hizo más madura. Tiene más sentido escribir código donde agreguemos un entrenador al final del tren (el tren se modela usando una lista vinculada) en lugar de agregar un nuevo nodo al final de la lista vinculada.
Codificación en términos de entidades del mundo real es simplemente la manera más obvia y adecuada de codificar cuando nos estamos codificando sobre las entidades del mundo real.
Una computadora puede trabajar agregando un nodo al final de la lista vinculada tan fácilmente como puede agregar un entrenador adicional al final del tren. Pero para los humanos es más fácil trabajar con el tren y el entrenador que con la lista y los nodos vinculados, aunque cuando vamos a un nivel profundo, encontramos que el tren se modela mediante una lista vinculada.
Proteger o cifrar los archivos no puede lograr la encapsulación. Lo opuesto al cifrado es el descifrado. Lo opuesto a la encapsulación es la decapsulación, que significa descomposición de estructuras y clases en lenguajes de programación para lograr un mejor rendimiento. El rendimiento obtenido al reducir el tráfico de memoria y evitar las verificaciones de las reglas de OOP
Por lo tanto, puede escribir código que esté encriptado y bien encapsulado porque estos dos son conceptos diferentes.
La encapsulación ayuda a gestionar la complejidad en virtud de estar cerca de la realidad.
Por lo tanto, programe en objetos porque es más fácil para usted codificar y es más rápido para usted y para todos los demás comprender.
fuente
Lo único que debe recordar es esto:
OOP no se trata de características del lenguaje; se trata de la forma en que estructura su código .
OOP es una forma de pensar y de diseñar la arquitectura de su código, y se puede hacer en casi cualquier idioma. Esto incluye especialmente los lenguajes de bajo nivel que no son OO, que se llaman ensamblador y C. Puede realizar una programación perfectamente orientada a objetos en ensamblador, y el núcleo de Linux, que está escrito en C, está bastante orientado a objetos en muchos aspectos .
Dicho esto, las características de OO en un idioma reducen en gran medida la cantidad de código repetitivo que necesita escribir para lograr los resultados deseados . Cuando necesite definir explícitamente una tabla de funciones virtuales y llenarla con los punteros de función apropiados en C, simplemente no hace nada en Java, y ya está. Los lenguajes OO simplemente eliminan todo lo que permite el cruft del código fuente, ocultándolo detrás de agradables abstracciones de nivel de lenguaje (como clases, métodos, miembros, clases base, llamadas implícitas de constructor / destructor, etc.).
Entonces, no, no necesitamos idiomas OO para hacer OOP. Es solo que OOP es mucho más fácil de hacer con un lenguaje OO decente.
fuente
La programación orientada a objetos es más que solo módulos + encapsulación. Como usted dice, es posible usar módulos + encapsulación en un lenguaje no orientado a objetos (de procedimiento). OOP implica más que solo eso: involucra objetos y métodos. Entonces, no, eso no captura la POO. Ver, por ejemplo, https://en.wikipedia.org/wiki/Object-oriented_programming o la introducción de un buen libro de texto a OOP.
fuente
La razón principal es que, a medida que un programa se vuelve más complejo, debe hacer que algunas partes del mismo sean invisibles de otras partes, o la complejidad de la aplicación y la cantidad de funciones harán que su cerebro gotee fuera de sus oídos.
Imaginemos un sistema de 100 clases, cada una con aproximadamente 20 operaciones que se pueden realizar en ellas; Eso son 2.000 funciones. Sin embargo, de esos, tal vez solo 500 son operaciones completas como 'Guardar' y 'Eliminar', mientras que 1500 son funciones internas que realizan un poco de mantenimiento o tienen alguna función de utilidad. Considerar;
Entonces,
SetName
es una función que las personas deberían estar haciendo a una persona, peroSplitPersonName
es una función de utilidad utilizada por la persona.La programación procesal directa no hace distinción entre estas dos operaciones. Eso significa que sus 2,000 funcionalidades compiten por su atención. Sin embargo, si pudiéramos marcar estas funciones como 'disponibles para todos los que tienen un registro de persona' y 'utilizadas solo como una función de utilidad dentro del registro de persona', entonces nuestra atención ahora es 500 'funciones disponibles para todos' y 15 'utilidad' funciones para la clase que estás editando.
Eso es
public
yprivate
hacer;fuente