La programación orientada a objetos ( POO ) es un paradigma de programación basado en el concepto de objetos , [1] que pueden contener datos y código : datos en forma de campos (a menudo conocidos como atributos o propiedades ) y código en forma de procedimientos. (a menudo conocidos como métodos ). En OOP, los programas de computadora se diseñan haciéndolos a partir de objetos que interactúan entre sí. [2] [3]
Muchos de los lenguajes de programación más utilizados (como C++ , Java , [4] Python , etc.) son multiparadigmas y soportan la programación orientada a objetos en mayor o menor grado, típicamente en combinación con programación imperativa , programación procedimental. y programación funcional .
Los lenguajes orientados a objetos importantes incluyen Ada , ActionScript , C++ , Common Lisp , C# , Dart , Eiffel , Fortran 2003 , Haxe , Java , [4] Kotlin , Logo , MATLAB , Objective-C , Object Pascal , Perl , PHP , Python , R , Raku , Ruby , Scala , SIMSCRIPT , Simula , Smalltalk , Swift , Vala y Visual Basic.NET .
La terminología que invoca "objetos" en el sentido moderno de programación orientada a objetos hizo su primera aparición en el grupo de inteligencia artificial del MIT a finales de los años cincuenta y principios de los sesenta. "Objeto" se refería a átomos LISP con propiedades (atributos) identificadas. [5] [6] Otro ejemplo temprano del MIT fue Sketchpad creado por Ivan Sutherland en 1960-1961; en el glosario del informe técnico de 1963 basado en su disertación sobre Sketchpad, Sutherland definió las nociones de "objeto" e "instancia" (con el concepto de clase cubierto por "maestro" o "definición"), aunque especializado en la interacción gráfica. [7] Asimismo, en 1968, una versión del MIT ALGOL , AED-0, estableció un vínculo directo entre estructuras de datos ("plexes", en ese dialecto) y procedimientos, prefigurando lo que más tarde se denominaría "mensajes", "métodos" y "funciones miembro". [8] [9] Temas como la abstracción de datos y la programación modular fueron puntos comunes de discusión en este momento.
Independientemente de trabajos posteriores del MIT, como el AED, Simula se desarrolló durante los años 1961-1967. [8] Simula introdujo conceptos importantes que hoy son una parte esencial de la programación orientada a objetos, como clase y objeto , herencia y enlace dinámico . [10] El lenguaje de programación Simula orientado a objetos fue utilizado principalmente por investigadores involucrados con el modelado físico , como modelos para estudiar y mejorar el movimiento de barcos y su contenido a través de los puertos de carga. [10]
Pensé en los objetos como células biológicas y/o computadoras individuales en una red, que sólo podían comunicarse con mensajes (por lo que la mensajería surgió desde el principio; tomó un tiempo ver cómo enviar mensajes en un lenguaje de programación lo suficientemente eficiente como para ser útil).
Alan Kay, [1]
Influenciado por el trabajo en el MIT y el lenguaje Simula, en noviembre de 1966 Alan Kay comenzó a trabajar en ideas que eventualmente se incorporarían al lenguaje de programación Smalltalk . Kay utilizó el término "programación orientada a objetos" en una conversación ya en 1967. [1] Aunque a veces se le llama "el padre de la programación orientada a objetos", [11] Alan Kay ha diferenciado su noción de OO de los datos abstractos más convencionales. noción tipo de objeto, y ha dado a entender que el establishment informático no adoptó su noción. [1] Un memorando del MIT de 1976 del que es coautora Barbara Liskov enumera Simula 67 , CLU y Alphard como lenguajes orientados a objetos, pero no menciona Smalltalk. [12]
En la década de 1970, Alan Kay , Dan Ingalls y Adele Goldberg desarrollaron la primera versión del lenguaje de programación Smalltalk en Xerox PARC . Smalltalk-72 incluía un entorno de programación y se escribía dinámicamente , y al principio se interpretaba , no se compilaba . Smalltalk se destacó por su aplicación de orientación a objetos a nivel de lenguaje y su entorno de desarrollo gráfico. Smalltalk pasó por varias versiones y creció el interés por el idioma. [13] Si bien Smalltalk fue influenciado por las ideas introducidas en Simula 67, fue diseñado para ser un sistema completamente dinámico en el que las clases pudieran crearse y modificarse dinámicamente. [14]
A finales de los años 1970 y 1980, la programación orientada a objetos saltó a la fama. El Lisp orientado a objetos de Flavors se desarrolló a partir de 1979, introduciendo herencia múltiple y mixins . [15] En 1981, Goldberg editó la edición de agosto de Byte Magazine , presentando Smalltalk y la programación orientada a objetos a una amplia audiencia. [16] LOOPS, el sistema de objetos para Interlisp -D, fue influenciado por Smalltalk y Flavors, y en 1982 se publicó un artículo al respecto. [17] En 1986, la Association for Computing Machinery organizó la primera Conferencia sobre Programación Orientada a Objetos. , Sistemas, Lenguajes y Aplicaciones (OOPSLA), al que asistieron 1.000 personas. Entre otros desarrollos se encuentra el Common Lisp Object System , que integra programación funcional y programación orientada a objetos y permite la extensión a través de un protocolo Meta-objeto . En la década de 1980, hubo algunos intentos de diseñar arquitecturas de procesador que incluyeran soporte de hardware para objetos en la memoria, pero no tuvieron éxito. Los ejemplos incluyen el Intel iAPX 432 y el Linn Smart Rekursiv .
A mediados de la década de 1980, Objective-C fue desarrollado por Brad Cox , que había utilizado Smalltalk en ITT Inc .. Bjarne Stroustrup , que había utilizado Simula para su tesis doctoral, creó el C++ orientado a objetos . [13] En 1985, Bertrand Meyer también realizó el primer diseño de la lengua Eiffel . Centrado en la calidad del software, Eiffel es un lenguaje de programación puramente orientado a objetos y una notación que respalda todo el ciclo de vida del software. Meyer describió el método de desarrollo de software de Eiffel, basado en una pequeña cantidad de ideas clave de la ingeniería de software y la informática, en Object-Oriented Software Construction . [18] Esencial para el enfoque de calidad de Eiffel es el mecanismo de confiabilidad de Meyer, el diseño por contrato , que es una parte integral tanto del método como del lenguaje.
A principios y mediados de la década de 1990, la programación orientada a objetos se desarrolló como el paradigma de programación dominante cuando los lenguajes de programación que soportaban estas técnicas estuvieron ampliamente disponibles. Estos incluían Visual FoxPro 3.0, [19] [20] [21] C++ , [22] y Delphi [ cita necesaria ] . Su dominio se vio reforzado aún más por la creciente popularidad de las interfaces gráficas de usuario , que dependen en gran medida de técnicas de programación orientada a objetos. Un ejemplo de una biblioteca GUI dinámica estrechamente relacionada y un lenguaje OOP se puede encontrar en los marcos Cocoa en Mac OS X , escritos en Objective-C , una extensión de mensajería dinámica orientada a objetos para C basada en Smalltalk. Los kits de herramientas de programación orientada a objetos también aumentaron la popularidad de la programación basada en eventos (aunque este concepto no se limita a la programación orientada a objetos).
En ETH Zürich , Niklaus Wirth y sus colegas investigaron el concepto de verificación de tipos a través de los límites de los módulos. Modula-2 (1978) incluyó este concepto, y su diseño posterior, Oberon (1987), incluyó un enfoque distintivo para la orientación de objetos, clases y demás. La herencia no es obvia en el diseño de Wirth ya que su nomenclatura mira en la dirección opuesta: se llama extensión de tipo y el punto de vista va desde el padre hasta el heredero.
Se han agregado funciones orientadas a objetos a muchos lenguajes existentes anteriormente, incluidos Ada , BASIC , Fortran , Pascal y COBOL . Agregar estas características a lenguajes que inicialmente no fueron diseñados para ellos a menudo generaba problemas de compatibilidad y mantenibilidad del código.
Más recientemente, han surgido algunos lenguajes que están principalmente orientados a objetos, pero que también son compatibles con la metodología procedimental. Dos de esos lenguajes son Python y Ruby . Probablemente los lenguajes orientados a objetos recientes de mayor importancia comercial sean Java , desarrollado por Sun Microsystems , así como C# y Visual Basic.NET (VB.NET), ambos diseñados para la plataforma .NET de Microsoft . Cada uno de estos dos marcos muestra, a su manera, el beneficio de usar programación orientada a objetos al crear una abstracción de la implementación. VB.NET y C# admiten la herencia entre idiomas, lo que permite que las clases definidas en un idioma subclasen las clases definidas en el otro idioma.
La programación orientada a objetos utiliza objetos, pero no todas las técnicas y estructuras asociadas son compatibles directamente con lenguajes que afirman ser compatibles con la programación orientada a objetos. Las características que se enumeran a continuación son comunes entre los lenguajes considerados fuertemente orientados a clases y objetos (o multiparadigmas con soporte para programación orientada a objetos), con excepciones notables mencionadas. [23] [24] [25] [26] Christopher J. Date afirmó que la comparación crítica de la POO con otras tecnologías, relacional en particular, es difícil debido a la falta de una definición rigurosa y acordada de la POO. [27]
El soporte de programación modular brinda la capacidad de agrupar procedimientos en archivos y módulos con fines organizativos. Los módulos tienen espacios de nombres para que los identificadores de un módulo no entren en conflicto con un procedimiento o variable que comparte el mismo nombre en otro archivo o módulo.
Un objeto es una estructura de datos o un tipo de datos abstracto que contiene campos ( variables de estado que contienen datos) y métodos ( subrutinas o procedimientos que definen el comportamiento del objeto en el código). Los campos también pueden denominarse miembros, atributos o propiedades. Los objetos normalmente se almacenan como regiones contiguas de la memoria . Se accede a los objetos de manera similar a variables con estructuras internas complejas y, en muchos lenguajes, son efectivamente punteros , que sirven como referencias reales a una única instancia de dicho objeto en la memoria dentro de un montón o pila.
Los objetos a veces corresponden a cosas que se encuentran en el mundo real. [28] Por ejemplo, un programa de gráficos puede tener objetos como "círculo", "cuadrado" y "menú". Un sistema de compras en línea puede tener objetos como "carrito de compras", "cliente" y "producto". A veces, los objetos representan entidades más abstractas, como un objeto que representa un archivo abierto o un objeto que proporciona el servicio de traducir medidas del sistema métrico estadounidense al sistema métrico.
Los objetos pueden contener otros objetos en sus variables de instancia; esto se conoce como composición de objetos . Por ejemplo, un objeto de la clase Empleado podría contener (ya sea directamente o mediante un puntero) un objeto de la clase Dirección, además de sus propias variables de instancia como "nombre" y "posición". La composición de objetos se utiliza para representar relaciones "tiene un": cada empleado tiene una dirección, por lo que cada objeto Empleado tiene acceso a un lugar para almacenar un objeto Dirección (ya sea directamente incrustado dentro de sí mismo o en una ubicación separada a la que se accede mediante un puntero). Date y Darwen han propuesto una base teórica que utiliza la programación orientada a objetos como una especie de sistema de tipos personalizable para admitir RDBMS , pero prohíbe los punteros a objetos. [29]
El paradigma OOP ha sido criticado por enfatizar demasiado el uso de objetos para el diseño y modelado de software a expensas de otros aspectos importantes (computación/algoritmos). [30] [31] Por ejemplo, Rob Pike ha dicho que los lenguajes OOP frecuentemente cambian el enfoque de las estructuras de datos y algoritmos a los tipos . [32] Steve Yegge señaló que, a diferencia de la programación funcional : [33]
La Programación Orientada a Objetos pone los sustantivos en primer lugar. ¿Por qué llegarías tan lejos para poner una parte del discurso en un pedestal? ¿Por qué un tipo de concepto debería tener prioridad sobre otro? No es que la POO de repente haya hecho que los verbos sean menos importantes en la forma en que realmente pensamos. Es una perspectiva extrañamente sesgada.
Rich Hickey , creador de Clojure , describió los sistemas de objetos como modelos demasiado simplistas del mundo real. Hizo hincapié en la incapacidad de la programación orientada a objetos para modelar el tiempo adecuadamente, lo que se está volviendo cada vez más problemático a medida que los sistemas de software se vuelven más concurrentes. [31]
Alexander Stepanov compara desfavorablemente la orientación a objetos con la programación genérica : [30]
Encuentro que la POO es técnicamente errónea. Intenta descomponer el mundo en términos de interfaces que varían en un solo tipo. Para abordar los problemas reales se necesitan álgebras multiclasificadas: familias de interfaces que abarquen múltiples tipos. Encuentro la programación orientada a objetos filosóficamente errónea. Afirma que todo es un objeto. Incluso si fuera cierto, no es muy interesante: decir que todo es un objeto es no decir nada en absoluto.
Los lenguajes de programación orientada a objetos son diversos, pero normalmente los lenguajes de programación orientada a objetos permiten la herencia para la reutilización y extensibilidad del código en forma de clases o prototipos . Estas formas de herencia son significativamente diferentes, pero se utiliza terminología análoga para definir los conceptos de objeto e instancia .
En la programación basada en clases , el estilo más popular, se requiere que cada objeto sea una instancia de una clase particular . La clase define el formato o tipo de datos (incluidas las variables miembro y sus tipos) y los procedimientos disponibles (métodos de clase o funciones miembro) para un tipo o clase de objeto determinado. Los objetos se crean llamando a un tipo especial de método en la clase conocido como constructor . Las clases pueden heredar de otras clases, por lo que están organizadas en una jerarquía que representa relaciones "es-un-tipo-de". Por ejemplo, la clase Empleado podría heredar de la clase Persona. Todos los datos y métodos disponibles para la clase principal también aparecen en la clase secundaria con los mismos nombres. Por ejemplo, la clase Persona podría definir las variables "nombre" y "apellido" con el método "make_full_name()". Estos también estarán disponibles en la clase Empleado, que podría agregar las variables "puesto" y "salario". Se garantiza que todas las instancias de la clase Empleado tendrán las mismas variables, como el nombre, el puesto y el salario. Los procedimientos y variables pueden ser específicos de la clase o de la instancia; esto lleva a los siguientes términos:
Dependiendo de la definición del lenguaje, las subclases pueden o no anular los métodos definidos por las superclases. En algunos idiomas se permite la herencia múltiple , aunque esto puede complicar la resolución de anulaciones. Algunos lenguajes tienen soporte especial para otros conceptos como rasgos y mixins , aunque, en cualquier lenguaje con herencia múltiple, un mixin es simplemente una clase que no representa una relación de tipo es-un. Los mixins se utilizan normalmente para agregar los mismos métodos a varias clases. Por ejemplo, la clase UnicodeConversionMixin podría proporcionar un método unicode_to_ascii() cuando se incluye en la clase FileReader y la clase WebPageScraper, que no comparten un padre común.
No se pueden crear instancias de clases abstractas en objetos; existen sólo para herencia en otras clases "concretas" de las que se pueden crear instancias. En Java, la final
palabra clave se puede utilizar para evitar que una clase se subclase. [34]
Por el contrario, en la programación basada en prototipos , los objetos son las entidades primarias. Generalmente, el concepto de "clase" ni siquiera existe. Más bien, el prototipo o padre de un objeto es simplemente otro objeto al que está vinculado. En Self, un objeto puede tener varios padres o ninguno, [35] pero en el lenguaje basado en prototipos más popular, Javascript, cada objeto tiene un enlace prototipo (y sólo uno). Se pueden crear nuevos objetos basados en objetos ya existentes elegidos como prototipo. Puedes llamar fruta a dos objetos diferentes manzana y naranja si el objeto fruta existe, y tanto la manzana como la naranja tienen fruta como prototipo. La idea de la clase fruta no existe explícitamente, pero puede modelarse como la clase de equivalencia de los objetos que comparten el mismo prototipo, o como el conjunto de objetos que satisfacen una determinada interfaz ( tipificación pato ). A diferencia de la programación basada en clases, en lenguajes basados en prototipos normalmente es posible definir atributos y métodos que no se comparten con otros objetos; por ejemplo, el atributo sugar_content puede estar definido en apple pero no en orange .
Algunos lenguajes como Go no admiten la herencia en absoluto. Go afirma que está orientado a objetos, [36] y Bjarne Stroustrup, autor de C++, ha declarado que es posible hacer programación orientada a objetos sin herencia. [37] La doctrina de la composición sobre la herencia aboga por implementar relaciones tiene-a utilizando la composición en lugar de la herencia. Por ejemplo, en lugar de heredar de la clase Persona, la clase Empleado podría darle a cada objeto Empleado un objeto Persona interno, que luego tiene la oportunidad de ocultar del código externo incluso si la clase Persona tiene muchos atributos o métodos públicos. La delegación es otra característica del lenguaje que se puede utilizar como alternativa a la herencia.
Rob Pike ha criticado la mentalidad OO por preferir una jerarquía de tipos multinivel con abstracciones en capas a una tabla de búsqueda de tres líneas . [38] Ha llamado a la programación orientada a objetos "los números romanos de la informática". [39]
Bob Martin afirma que debido a que son software, las clases relacionadas no necesariamente comparten las relaciones de las cosas que representan. [40]
Es responsabilidad del objeto, no de ningún código externo, seleccionar el código de procedimiento a ejecutar en respuesta a una llamada a un método, generalmente buscando el método en tiempo de ejecución en una tabla asociada con el objeto. Esta característica se conoce como despacho dinámico . Si la variabilidad de la llamada depende de más que el único tipo de objeto sobre el cual se llama (es decir, al menos otro objeto de parámetro está involucrado en la elección del método), se habla de despacho múltiple . Una llamada a un método también se conoce como paso de mensajes . Se conceptualiza como un mensaje (el nombre del método y sus parámetros de entrada) que se pasa al objeto para su envío.
El envío interactúa con la herencia; si un método no está presente en un objeto o clase determinado, el envío se delega a su objeto o clase padre, y así sucesivamente, ascendiendo en la cadena de herencia.
La abstracción de datos es un patrón de diseño en el que los datos son visibles sólo para funciones relacionadas semánticamente, para evitar un uso indebido. El éxito de la abstracción de datos conduce a la incorporación frecuente del ocultamiento de datos como principio de diseño en la programación puramente funcional y orientada a objetos. De manera similar, la encapsulación evita que el código externo se ocupe del funcionamiento interno de un objeto. Esto facilita la refactorización de código , permitiendo por ejemplo al autor de la clase cambiar la forma en que los objetos de esa clase representan sus datos internamente sin cambiar ningún código externo (siempre que las llamadas a métodos "públicos" funcionen de la misma manera). También anima a los programadores a poner todo el código relacionado con un determinado conjunto de datos en la misma clase, lo que lo organiza para que otros programadores lo comprendan fácilmente. La encapsulación es una técnica que fomenta el desacoplamiento .
En la programación orientada a objetos, los objetos proporcionan una capa que se puede utilizar para separar el código interno del externo e implementar la abstracción y la encapsulación. El código externo solo puede usar un objeto llamando a un método de instancia específico con un determinado conjunto de parámetros de entrada, leyendo una variable de instancia o escribiendo en una variable de instancia. Un programa puede crear muchas instancias de objetos mientras se ejecuta, que operan de forma independiente. Se afirma que esta técnica permite una fácil reutilización de los mismos procedimientos y definiciones de datos para diferentes conjuntos de datos, además de reflejar potencialmente las relaciones del mundo real de forma intuitiva. En lugar de utilizar tablas de bases de datos y subrutinas de programación, el desarrollador utiliza objetos con los que el usuario puede estar más familiarizado: objetos de su dominio de aplicación. [41] Estas afirmaciones de que el paradigma OOP mejora la reutilización y la modularidad han sido criticadas. [42] [43]
Si una clase no permite llamar al código para acceder a datos de objetos internos y permite el acceso solo a través de métodos, esto también es una forma de ocultar información. Algunos lenguajes (Java, por ejemplo) permiten que las clases apliquen restricciones de acceso explícitamente, por ejemplo, denotando datos internos con la private
palabra clave y designando métodos destinados a ser utilizados por código fuera de la clase con la public
palabra clave. [44] También se pueden diseñar métodos públicos, privados o de niveles intermedios como protected
(que permite el acceso desde la misma clase y sus subclases, pero no a objetos de una clase diferente). [44] En otros lenguajes (como Python), esto se aplica solo por convención (por ejemplo, private
los métodos pueden tener nombres que comiencen con un guión bajo ). En los lenguajes C#, Swift y Kotlin, internal
la palabra clave permite el acceso solo a archivos presentes en el mismo ensamblado, paquete o módulo que el de la clase. [45]
En los lenguajes de programación, particularmente los orientados a objetos, el énfasis en la abstracción es vital. Los lenguajes orientados a objetos amplían la noción de tipo para incorporar la abstracción de datos, destacando la importancia de restringir el acceso a los datos internos a través de métodos. [46] Eric S. Raymond ha escrito que los lenguajes de programación orientados a objetos tienden a fomentar programas con capas gruesas que destruyen la transparencia. [47] Raymond compara esto desfavorablemente con el enfoque adoptado con Unix y el lenguaje de programación C. [47]
El " principio abierto/cerrado " defiende que las clases y funciones "deben estar abiertas a la extensión, pero cerradas a la modificación". Luca Cardelli ha afirmado que los lenguajes POO tienen "propiedades de modularidad extremadamente pobres con respecto a la extensión y modificación de clases" y tienden a ser extremadamente complejos. [42] Este último punto es reiterado por Joe Armstrong , el principal inventor de Erlang , quien se cita diciendo: [43]
El problema con los lenguajes orientados a objetos es que tienen todo este entorno implícito que llevan consigo. Querías un plátano pero lo que obtuviste fue un gorila sosteniendo el plátano y toda la jungla.
Leo Brodie ha sugerido una conexión entre la naturaleza independiente de los objetos y una tendencia a duplicar código [48] en violación del principio de no repetirse [49] del desarrollo de software.
La subtipificación (una forma de polimorfismo ) ocurre cuando el código de llamada puede ser independiente de en qué clase de la jerarquía admitida está operando: la clase principal o uno de sus descendientes. Mientras tanto, el mismo nombre de operación entre objetos en una jerarquía de herencia puede comportarse de manera diferente.
Por ejemplo, los objetos del tipo Círculo y Cuadrado se derivan de una clase común llamada Forma. La función Dibujar para cada tipo de Forma implementa lo necesario para dibujarse a sí mismo, mientras que el código de llamada puede permanecer indiferente al tipo particular de Forma que se está dibujando.
Este es otro tipo de abstracción que simplifica el código externo a la jerarquía de clases y permite una fuerte separación de preocupaciones .
Una característica común de los objetos es que se les adjuntan métodos que pueden acceder y modificar los campos de datos del objeto. En este tipo de programación orientada a objetos, suele haber un nombre especial como thiso self
que se utiliza para referirse al objeto actual. En los lenguajes que admiten la recursividad abierta , los métodos de objeto pueden llamar a otros métodos en el mismo objeto (incluidos ellos mismos) usando este nombre. Esta variable está enlazada en tiempo de ejecución ; permite que un método definido en una clase invoque otro método que se define posteriormente, en alguna subclase de la misma.
Simula (1967) es generalmente aceptado como el primer lenguaje con las características principales de un lenguaje orientado a objetos. Fue creado para realizar programas de simulación , en los que lo que se dio en llamar objetos eran la representación de información más importante. Smalltalk (1972 a 1980) es otro ejemplo temprano y con el que se desarrolló gran parte de la teoría de la POO. En cuanto al grado de orientación a objetos, se pueden hacer las siguientes distinciones:
Muchos lenguajes ampliamente utilizados, como C++, Java y Python, proporcionan funciones orientadas a objetos. Aunque en el pasado la programación orientada a objetos era ampliamente aceptada, [51] ensayos más recientes que critican la programación orientada a objetos y recomiendan evitar estas características (generalmente a favor de la programación funcional ) han sido muy populares en la comunidad de desarrolladores. [52] Paul Graham ha sugerido que la popularidad de la programación orientada a objetos dentro de las grandes empresas se debe a "grandes (y frecuentemente cambiantes) grupos de programadores mediocres". Según Graham, la disciplina impuesta por la programación orientada a objetos impide que un programador "haga demasiado daño". [53] Eric S. Raymond , programador de Unix y defensor del software de código abierto , ha criticado las afirmaciones que presentan la programación orientada a objetos como la "única solución verdadera". [47]
Richard Feldman sostiene que estos lenguajes pueden haber mejorado su modularidad al agregar características OO, pero se hicieron populares por razones distintas a estar orientadas a objetos. [54] En un artículo, Lawrence Krubner afirmó que, en comparación con otros lenguajes (dialectos LISP, lenguajes funcionales, etc.), los lenguajes OOP no tienen fortalezas únicas e imponen una pesada carga de complejidad innecesaria. [55] Un estudio de Potok et al. no ha mostrado diferencias significativas en la productividad entre la programación orientada a objetos y los enfoques procedimentales. [56] Luca Cardelli ha afirmado que el código POO es "intrínsecamente menos eficiente" que el código procesal y que la POO puede tardar más en compilarse. [42]
En los últimos años, la programación orientada a objetos se ha vuelto especialmente popular en los lenguajes de programación dinámicos . Python , PowerShell , Ruby y Groovy son lenguajes dinámicos construidos sobre principios de programación orientada a objetos, mientras que Perl y PHP han agregado características orientadas a objetos desde Perl 5 y PHP 4, y ColdFusion desde la versión 6.
El modelo de objetos de documento de documentos HTML , XHTML y XML en Internet tiene enlaces al popular lenguaje JavaScript / ECMAScript . JavaScript es quizás el lenguaje de programación basado en prototipos más conocido , que emplea la clonación de prototipos en lugar de heredar de una clase (a diferencia de la programación basada en clases ). Otro lenguaje de programación que adopta este enfoque es Lua .
Los mensajes que fluyen entre computadoras para solicitar servicios en un entorno cliente-servidor pueden diseñarse como linealizaciones de objetos definidos por objetos de clase conocidos tanto por el cliente como por el servidor. Por ejemplo, un objeto linealizado simple consistiría en un campo de longitud, un punto de código que identifica la clase y un valor de datos. Un ejemplo más complejo sería un comando que consta de la longitud y el punto de código del comando y valores que consisten en objetos linealizados que representan los parámetros del comando. Cada uno de estos comandos debe ser dirigido por el servidor a un objeto cuya clase (o superclase) reconozca el comando y pueda proporcionar el servicio solicitado. Los clientes y servidores se modelan mejor como estructuras complejas orientadas a objetos. La Arquitectura de gestión de datos distribuida (DDM) adoptó este enfoque y utilizó objetos de clase para definir objetos en cuatro niveles de una jerarquía formal:
La versión inicial de DDM definió servicios de archivos distribuidos. Posteriormente se amplió hasta convertirse en la base de la Arquitectura de bases de datos relacionales distribuidas (DRDA).
Una forma de abordar los desafíos del diseño orientado a objetos es a través de patrones de diseño que son patrones de solución a problemas que ocurren comúnmente en el diseño de software. Algunos de estos problemas que ocurren comúnmente tienen implicaciones y soluciones particulares del desarrollo orientado a objetos.
Los siguientes son patrones de diseño de software notables para objetos OOP. [57]
operator()
), actúa de manera muy similar a una función.Como ejemplo de antipatrón de objeto , el objeto Dios sabe o hace demasiado.
Es intuitivo suponer que la herencia crea una relación semántica " es un " y, por lo tanto, inferir que los objetos instanciados a partir de subclases siempre se pueden usar con seguridad en lugar de aquellos instanciados a partir de la superclase. Lamentablemente, esta intuición es falsa en la mayoría de los lenguajes de programación orientada a objetos, en particular en todos aquellos que permiten objetos mutables . El polimorfismo de subtipo aplicado por el verificador de tipos en lenguajes OOP (con objetos mutables) no puede garantizar el subtipo de comportamiento en ningún contexto. La subtipificación del comportamiento es indecidible en general, por lo que no puede ser implementada por un programa (compilador). Las jerarquías de clases u objetos deben diseñarse cuidadosamente, considerando posibles usos incorrectos que no pueden detectarse sintácticamente. Esta cuestión se conoce como principio de sustitución de Liskov .
Patrones de diseño: elementos de software reutilizable orientado a objetos es un libro influyente publicado en 1994 por Erich Gamma , Richard Helm , Ralph Johnson y John Vlissides , a menudo referido con humor como la "Banda de los Cuatro". Además de explorar las capacidades y dificultades de la programación orientada a objetos, describe 23 problemas de programación comunes y patrones para resolverlos.
El libro describe los siguientes patrones:
Tanto la programación orientada a objetos como los sistemas de gestión de bases de datos relacionales (RDBMS) son extremadamente comunes en el software actual [update]. Dado que las bases de datos relacionales no almacenan objetos directamente (aunque algunos RDBMS tienen características orientadas a objetos para aproximarse a esto), existe una necesidad general de unir los dos mundos. El problema de unir los accesos a la programación orientada a objetos y los patrones de datos con las bases de datos relacionales se conoce como desajuste de impedancia relacional entre objetos . Existen algunos enfoques para afrontar este problema, pero no hay una solución general sin desventajas. [58] Uno de los enfoques más comunes es el mapeo objeto-relacional , como se encuentra en lenguajes IDE como Visual FoxPro y bibliotecas como Java Data Objects y ActiveRecord de Ruby on Rails .
También existen bases de datos de objetos que se pueden utilizar para reemplazar los RDBMS, pero no han tenido tanto éxito técnico y comercial como los RDBMS.
La programación orientada a objetos se puede utilizar para asociar objetos y procesos del mundo real con sus homólogos digitales. Sin embargo, no todo el mundo está de acuerdo en que la programación orientada a objetos facilita el mapeo directo del mundo real o que el mapeo del mundo real sea siquiera un objetivo digno; Bertrand Meyer sostiene en Object-Oriented Software Construction que un programa no es un modelo del mundo sino un modelo de alguna parte del mundo; "La realidad es una prima dos veces eliminada". [59] Al mismo tiempo, se han observado algunas limitaciones principales de la programación orientada a objetos. [60] Por ejemplo, el problema círculo-elipse es difícil de manejar utilizando el concepto de herencia de la programación orientada a objetos .
Sin embargo, Niklaus Wirth (quien popularizó el adagio ahora conocido como ley de Wirth : "El software se vuelve más lento más rápidamente que el hardware") dijo sobre la programación orientada a objetos en su artículo "Buenas ideas a través del espejo": "Este paradigma refleja fielmente la estructura de sistemas en el mundo real y, por lo tanto, es muy adecuado para modelar sistemas complejos con comportamiento complejo" [61] ( principio KISS de contraste ).
Steve Yegge y otros notaron que los lenguajes naturales carecen del enfoque POO de priorizar estrictamente las cosas (objetos/ sustantivos ) antes que las acciones (métodos/ verbos ). [62] Este problema puede hacer que la programación orientada a objetos sufra soluciones más complicadas que la programación procesal. [63]
La programación orientada a objetos se desarrolló para aumentar la reutilización y la mantenibilidad del código fuente. [64] La representación transparente del flujo de control no tenía prioridad y estaba destinada a ser manejada por un compilador. Con la creciente relevancia del hardware paralelo y la codificación multiproceso , desarrollar un flujo de control transparente se vuelve más importante, algo difícil de lograr con programación orientada a objetos. [65] [66] [67] [68]
El diseño basado en responsabilidad define clases en términos de un contrato, es decir, una clase debe definirse en torno a una responsabilidad y la información que comparte. Wirfs-Brock y Wilkerson contrastan esto con el diseño basado en datos , donde las clases se definen en torno a las estructuras de datos que deben mantenerse. Los autores sostienen que es preferible el diseño impulsado por la responsabilidad.
SOLID es un mnemotécnico inventado por Michael Feathers que detalla cinco principios de diseño de ingeniería de software:
GRASP (Patrones de software de asignación de responsabilidad general) es otro conjunto de pautas defendidas por Craig Larman .
Los objetos son las entidades de tiempo de ejecución en un sistema orientado a objetos. Pueden representar una persona, un lugar, una cuenta bancaria, una tabla de datos o cualquier elemento que el programa deba manejar.
Ha habido varios intentos de formalizar los conceptos utilizados en la programación orientada a objetos. Los siguientes conceptos y construcciones se han utilizado como interpretaciones de conceptos de programación orientada a objetos:
Los intentos de encontrar una definición o teoría consensuada detrás de los objetos no han resultado muy exitosos (sin embargo, ver Abadi & Cardelli, A Theory of Objects [70] para definiciones formales de muchos conceptos y construcciones de programación orientada a objetos), y a menudo divergen ampliamente. Por ejemplo, algunas definiciones se centran en actividades mentales y otras en la estructuración de programas. Una de las definiciones más simples es que la programación orientada a objetos es el acto de utilizar matrices o estructuras de datos de "mapas" que pueden contener funciones y punteros a otros mapas, todo con algo de azúcar sintáctico y de alcance en la parte superior. La herencia se puede realizar clonando los mapas (a veces llamado "creación de prototipos").
En el dialecto local del MIT, las listas de asociaciones [de símbolos atómicos] también se denominan "listas de propiedades", y los símbolos atómicos a veces se denominan "objetos".
Objeto: sinónimo de símbolo atómico
Quizás la mayor fortaleza de un enfoque del desarrollo orientado a objetos es que ofrece un mecanismo que captura un modelo del mundo real.
Aunque Go tiene tipos y métodos y permite un estilo de programación orientado a objetos, no existe una jerarquía de tipos.
La programación orientada a objetos es un paradigma de programación ampliamente aceptado.