Posteriormente a investigar en diferentes repositorios y páginas al concluir nos hemos encontrado la resolución que te compartimos aquí.
Solución:
Aquí hay alrededor de cien problemas de terminología, en su mayoría construidos alrededor de alguien (no usted) que intenta hacer que su idea suene como The Best.
Todos los lenguajes orientados a objetos deben poder manejar varios conceptos:
- encapsulación de datos junto con operaciones asociadas en los datos, conocidas como miembros de datos y funciones de miembros, o como datos y métodos, entre otras cosas.
- herencia, la capacidad de decir que estos objetos son como ese otro conjunto de objetos EXCEPTO por estos cambios
- polimorfismo (“muchas formas”) en el que un objeto decide por sí mismo qué métodos se ejecutarán, de modo que puede depender del idioma para enrutar sus solicitudes correctamente.
Ahora, en cuanto a la comparación:
Lo primero es toda la cuestión de “clase” vs “prototipo”. La idea comenzó originalmente en Simula, donde con un método basado en clases, cada clase representaba un conjunto de objetos que compartían el mismo espacio de estado (léase “valores posibles”) y las mismas operaciones, formando así una clase de equivalencia. Si mira hacia atrás en Smalltalk, dado que puede abrir una clase y agregar métodos, esto es efectivamente lo mismo que puede hacer en Javascript.
Los lenguajes OO posteriores querían poder usar static Comprobación de tipo, por lo que obtuvimos la noción de una clase fija establecida en tiempo de compilación. En la versión de clase abierta, tenías más flexibilidad; en la versión más reciente, tenía la capacidad de verificar algunos tipos de corrección en el compilador que, de lo contrario, habrían requerido pruebas.
En un lenguaje “basado en clases”, esa copia ocurre en tiempo de compilación. En un lenguaje prototipo, las operaciones se almacenan en la estructura de datos prototipo, que se copia y modifica en tiempo de ejecución. Sin embargo, de manera abstracta, una clase sigue siendo la clase de equivalencia de todos los objetos que comparten el mismo espacio de estado y métodos. Cuando agrega un método al prototipo, está creando efectivamente un elemento de una nueva clase de equivalencia.
Ahora, ¿por qué hacer eso? principalmente porque lo convierte en un mecanismo simple, lógico y elegante en tiempo de ejecución. ahora, para crear un nuevo objeto, o para crear una nueva clase, simplemente hay que realizar una copia profunda, copiando todos los datos y la estructura de datos del prototipo. Obtiene herencia y polimorfismo más o menos gratis entonces: búsqueda de método siempre consiste en pedir a un diccionario la implementación de un método por su nombre.
La razón por la que terminó en el script Javascript/ECMA es básicamente que cuando comenzamos con esto hace 10 años, lidiamos con computadoras mucho menos poderosas y navegadores mucho menos sofisticados. La elección del método basado en prototipos significaba que el intérprete podía ser muy simple al tiempo que conservaba las propiedades deseables de la orientación a objetos.
Se puede encontrar una comparación, que está ligeramente sesgada hacia el enfoque basado en prototipos, en el artículo Self: The Power of Simplicity. El documento presenta los siguientes argumentos a favor de los prototipos:
Creación por copia. La creación de nuevos objetos a partir de prototipos se logra mediante una operación simple, la copia, con una simple metáfora biológica, la clonación. La creación de nuevos objetos a partir de clases se logra mediante la creación de instancias, que incluye la interpretación de la información de formato en una clase. La instanciación es similar a construir una casa a partir de un plano. Copiar nos atrae como una metáfora más simple que la instanciación.
Ejemplos de módulos preexistentes. Los prototipos son más concretos que las clases porque son ejemplos de objetos en lugar de descripciones de formato e inicialización. Estos ejemplos pueden ayudar a los usuarios a reutilizar módulos haciéndolos más fáciles de entender. Un sistema basado en prototipos le permite al usuario examinar un representante típico en lugar de pedirle que le dé sentido a su descripción.
Soporte para objetos únicos. Self proporciona un marco que puede incluir fácilmente objetos únicos con su propio comportamiento. Dado que cada objeto tiene ranuras con nombre, y las ranuras pueden tener estado o comportamiento, cualquier objeto puede tener ranuras o comportamiento únicos. Los sistemas basados en clases están diseñados para situaciones en las que hay muchos objetos con el mismo comportamiento. No hay soporte lingüístico para que un objeto posea su propio comportamiento único, y es incómodo crear una clase que garantice tener solo una instancia. [think singleton
pattern]. Self no sufre de ninguna de estas desventajas. Cualquier objeto se puede personalizar con su propio comportamiento. Un objeto único puede contener el comportamiento único y no se necesita una “instancia” separada.Eliminación del metarregreso. Ningún objeto en un sistema basado en clases puede ser autosuficiente; se necesita otro objeto (su clase) para expresar su estructura y comportamiento. Esto conduce a un meta-regreso conceptualmente infinito: un
point
es una instancia de clasePoint
que es una instancia de la metaclasePoint
que es una instancia de metametaclase
Point
, hasta el infinito. Por otro lado, en los sistemas basados en prototipos un objeto puede incluir su propio comportamiento; no se necesita ningún otro objeto para darle vida. Los prototipos eliminan el metarregreso.
Self es probablemente el primer lenguaje en implementar prototipos (también fue pionero en otras tecnologías interesantes como JIT, que luego se abrió paso en JVM), por lo que leer los otros documentos de Self también debería ser instructivo.
Deberías revisar un Gran libro sobre JavaScript de Douglas Crockford. Proporciona una muy buena explicación de algunas de las decisiones de diseño tomadas por los creadores de JavaScript.
Uno de los aspectos de diseño importantes de JavaScript es su sistema de herencia de prototipos. Los objetos son ciudadanos de primera clase en JavaScript, tanto que las funciones regulares también se implementan como objetos (objeto ‘Función’ para ser precisos). En mi opinión, cuando se diseñó originalmente para ejecutarse dentro de un navegador, estaba destinado a ser utilizado para crear muchos objetos singleton. En el navegador DOM, encuentra esa ventana, documento, etc., todos los objetos únicos. Además, JavaScript es un lenguaje dinámico poco tipificado (a diferencia de Python, que es un lenguaje dinámico fuertemente tipado), como resultado, se implementó un concepto de extensión de objeto mediante el uso de la propiedad ‘prototipo’.
Así que creo que hay algunas ventajas para la OO basada en prototipos tal como se implementa en JavaScript:
- Apropiado en entornos de tipos poco definidos, sin necesidad de definir tipos explícitos.
- Hace que sea increíblemente fácil implementar el patrón singleton (compare JavaScript y Java a este respecto, y sabrá de lo que estoy hablando).
- Proporciona formas de aplicar un método de un objeto en el contexto de un objeto diferente, agregando y reemplazando métodos dinámicamente desde un objeto, etc. (cosas que no son posibles en lenguajes fuertemente tipados).
Estas son algunas de las desventajas del OO prototipo:
- No es una forma fácil de implementar variables privadas. Es posible implementar variables privadas usando la magia de Crockford usando cierres, pero definitivamente no es tan trivial como usar variables privadas en, por ejemplo, Java o C#.
- Todavía no sé cómo implementar herencias múltiples (por lo que vale) en JavaScript.
Ten en cuenta comunicar este escrito si te ayudó.